제리의 블로그

TokyoWesterns CTF 4th 2018 twctf dec_dec_dec 본문

CTF/reversing

TokyoWesterns CTF 4th 2018 twctf dec_dec_dec

j3rrry 2018. 9. 4. 17:51

요약

리버싱 문제로
flag 를 base64, rot13, 또 다른 인코딩.
이렇게 3단계 인코딩을 거쳐 strcmp로 비교한다.
(세번째 인코딩은 uu 인코딩이란다)
풀이방법은 gdb script 로 브루트포싱을 했습니다.



void __fastcall main(int argc, char **argv, char **env)
{
  size_t len; // rax@4
  char *flag; // ST18_8@4
  size_t len_; // rdx@4
  char *enc1; // rax@4
  char *enc2; // rax@4
  char *enc3; // ST18_8@4

  if ( argc != 2 )
  {
    puts("./dec_dec_dec flag_string_is_here ");
    exit(0);
  }
  len = strlen(argv[1]);
  flag = (char *)malloc(len + 1);
  len_ = strlen(argv[1]);
  strncpy(flag, argv[1], len_);
  enc1 = base64enc(flag);
  enc2 = rot13(enc1);
  enc3 = uuencode(enc2);
  if ( !strcmp(enc3, "@25-Q44E233=,>E-M34=,,$LS5VEQ45)M2S-),7-$/3T ") )
    puts("correct  :)");
  else
    puts("incorrect :(");
}
메인을 보면 입력값(flag)을
base64 인코딩을하고
rot13 인코딩을하고
또 다른 인코딩(uuencode)을 한번 더 한 값을
특정 문자열과 비교하고 있었습니다.
고정된 문자열이라서 브포로 어떻게 비벼볼 수 있을거 같습니다.

base64, rot13 같은 인코딩은 input 길이와 output 길이가 비례하기 때문에
flag의 길이를 파악하는 것은 간단했습니다.
일단 TWCTF{aaaaaaaaaaaaaaa}로 초기화한 상태에서 하나하나 찾았습니다.



# ./dec_dec_dec TWCTF{base64_rot13_uu}
correct  :)



import string

ip = dec_dec_dec.entry + (0x1109 - 0x730)
gdb.Breakpoint('*' + hex(ip))
flag = list('base64_rot13_uu')
rsi = '@25-Q44E233=,>E-M34=,,$LS5VEQ45)M2S-),7-$/3T '
idx = 14
chset = string.ascii_lowercase+string.digits+'_'

l = []

for c in chset:
    flag[idx] = c
    flag2 = 'TWCTF{' + ''.join(flag) + '}'
    gdb.execute('r ' + flag2)
    print(flag2)

    rdi = gdb.parse_and_eval('$rdi')
    rdi = gdb.execute('printf "%s", ' + hex(rdi), to_string=True)
    print(rdi)
    print(rsi)
    #   @25-Q44E233=,>E-M34=,,$LS5VEQ45)M2S-),7-$/3T
    if '@25-Q44E233=,>E-M34=,,$LS5VEQ45)M2S-),7-$/3T ' in rdi:
        print("[+] found!")
        l += [c]
        #break
print(l)
gdb.execute('q')



10분 걸리는 gdb 브루트포스 스크립트

import string

######## inital ########
#flag = list('base64_rot13_uu')
flag = list('aaaaaaaaaaaaaaa')
idx = 0
chset = string.ascii_lowercase+string.digits+'_'
#chset = '0ubase64_rot13'
########################

ip = dec_dec_dec.entry + (0x1109 - 0x730)
bp = gdb.Breakpoint('*' + hex(ip))
bp.silent = True
rsi = '@25-Q44E233=,>E-M34=,,$LS5VEQ45)M2S-),7-$/3T '

def set_pivot():
        flag2 = 'TWCTF{' + ''.join(flag) + '}'
        gdb.execute('r ' + flag2)

        rdi = gdb.parse_and_eval('$rdi')
        rdi = gdb.execute('printf "%s", ' + hex(rdi), to_string=True)

        pivot = 0
        for i in range(len(rdi)):
                if rdi[i] == rsi[i]:
                        pivot += 1
                else: break
        pivot += 1

        return pivot

pivot = set_pivot()
print('pivot = {}'.format(pivot))

def check(idx, pivot, chset):
        candidate = []
        for c in chset:
            flag[idx] = c
            flag2 = 'TWCTF{' + ''.join(flag) + '}'
            gdb.execute('r ' + flag2)
            print(flag2)

            rdi = gdb.parse_and_eval('$rdi')
            rdi = gdb.execute('printf "%s", ' + hex(rdi), to_string=True)
            print(rdi)
            print(rsi)
            if rsi[:pivot] in rdi:
                print("found!")
                candidate += [c]
        print('candidate: {}'.format(candidate))
        return candidate

chset2 = chset
is_loop = 0
stack = []
while idx < len(flag):
        l2 = check(idx, pivot, chset2)
        if not l2:
                if stack and stack[-1][0] == idx - 1:
                        print('Before STACK: {}'.format(stack))
                        flag[idx-1] = stack[-1][1].pop(0)
                        if not len(stack[-1][1]):
                                del stack[-1]
                        print('After STACK: {}'.format(stack))
                else:
                        is_loop += 1
                        pivot -= 1
        elif len(l2) == 1:
                is_loop = 0
                flag[idx] = l2[0]
                chset2 = chset
                pivot += 1
                idx += 1
        elif len(l2) == len(chset):
                idx -= 1
                if stack and stack[-1][0] == idx:
                        print('Before STACK: {}'.format(stack))
                        flag[idx] = stack[-1][1].pop(0)
                        if not len(stack[-1][1]):
                                del stack[-1]
                        print('After STACK: {}'.format(stack))
                        idx += 1
                        pivot += 1
        else:
                is_loop *= 2
                chset2 = l2
                pivot += 1
        if is_loop > 7:
                print('[-] loop!')
                if not stack:
                        stack += [[idx, l2]]
                elif stack[-1][0] == idx:
                        pass
                else:
                        stack += [[idx, l2]]
                print('Before STACK: {}'.format(stack))
                if not stack:
                        print('[-] Error')
                idx = stack[-1][0]
                flag[idx] = stack[-1][1].pop(0)
                if not len(stack[-1][1]):
                        del stack[-1]
                print('After STACK: {}'.format(stack))
                is_loop = 0
                idx += 1
                chset2 = chset
print('TWCTF{' + ''.join(flag) + '}')
gdb.execute('q')
'''
real    9m43.874s
user    8m36.962s
sys     0m44.821s
'''



이건 6분짜리 브포
import string

######## inital ########
flag = list('abaaaaaaaaaaaaa')
idx = 0
chset = string.ascii_lowercase+string.digits+'_'
########################

ip = dec_dec_dec.entry + (0x1109 - 0x730)
bp = gdb.Breakpoint('*' + hex(ip))
bp.silent = True
rsi = '@25-Q44E233=,>E-M34=,,$LS5VEQ45)M2S-),7-$/3T '

pivot = -1
chset2 = chset

while idx < len(flag):
        if flag[idx] == chset[-1]: # 못찾음
                flag[idx] = chset[0]
                idx -= 1
                pivot -= 1
                a02 = chset.index(flag[idx])
                chset2 = chset[a02+1:]
        else:
                chset2 = chset

        c2 = ''
        for c in chset2:
                flag[idx] = c
                flag2 = 'TWCTF{' + ''.join(flag) + '}'
                gdb.execute('r ' + flag2)
                print(flag2)

                rdi = gdb.parse_and_eval('$rdi')
                rdi = gdb.execute('printf "%s", ' + hex(rdi), to_string=True)
                print(rdi)
                print(rsi)

                if pivot < 0: # init pivot
                        for i in range(len(rsi)):
                                if rsi[i] == rdi[i]:
                                        pivot = i
                                else: break
                        #pivot += 1
                        continue

                tmp = 0
                for i in range(pivot+1, len(rsi)):
                        if rsi[i] == rdi[i]:
                                tmp = i
                        else: break
                if tmp > pivot:
                        print('found!')
                        c2 = c
                        #idx += 1
                        pivot = tmp
                        #chset2 = chset
                        #break
        if c2:
                flag[idx] = c2
                idx += 1
print('TWCTF{' + ''.join(flag) + '}')
gdb.execute('q')
'''
real    5m58.036s
user    5m17.771s
sys     0m27.468s
'''


Comments