De1ctf2019-Re_Sign
De1ctf2019의 Re_Sign 이라는 문제였고 문제 설명에는 UPX라고 적혀있었다.
올리 디버거로 MUP 방식으로 덤프를 뜨고 ida로 동적디버깅 해보려고했는데 kernel32.dll 오류때문에 할수없어서
ida는 정적으로, immunity 디버거를 동적으로 사용하면서 분석했다.
분석을 해보니 custom table base64 encrypt를 한 플래그의 길이가 48글자 인지 체크하고
테이블이 맞는지 비교하고
문자열의 길이대로 모두 맞는지 확인한다.
플래그가 맞으면 success를 아니라면 fail을 출력한다.
즉 테이블만 알면 복호화할수 있는데
이 과정에서 이 테이블과
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
이 테이블을 이용한다.
import string,base64
table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
m=[0x08,0x3B,0x01,0x20,0x07,0x34,0x09,0x1F,0x18,0x24,0x13,0x03,0x10,0x38,0x09,0x1B,0x08,0x34,0x13,0x02,0x08,0x22,0x12,0x03, 0x05,0x06,0x12,0x03,0x0F,0x22,0x12,0x17,0x08,0x01,0x29,0x22,0x06,0x24,0x32,0x24,0x0F,0x1F,0x2B,0x24,0x03,0x15,0x41,0x41]
enc=''
for i in range(len(m)):
enc+=table[m[i]-1]
enc="H6AfGzIeXjSCP3IaHzSBHhRCEFRCOhRWHAohFjkjOeqjCU=="
table=base64.b64encode(table)
arr="UA93I4S6IjB9OqpEPAcYA55OAkISSwZGDSyBGeRqHDHrJ6wuJlfpKemdLF9hZ7SlZzBcXM0fEMEjRPGzT3qiWhj="
tb=string.maketrans(arr,table)
rb=enc.translate(tb)
print(base64.b64decode(rb))
알아낸 정보들로 올바른 테이블을 만들어 주고 복호화하면
de1ctf{EBL4Zguag3B1sBK3KeJ3_MtJi4
중간에 몇몇 문자열이 base64collision이 일어나서 플래그가 이상하게 나오는데 이부분을 직접 디버깅하면서 수정했다.
FLAG:de1ctf{E_L4nguag3_1s_K3KeK3_N4Ji4}
Success!!
xctf 관련 대회 문제는 항상 한문제도 못풀었는데 이번에는
풀어서 다행이다.
대회 공식 write-up을 보다가 내가 분석하다가 무심코 넘겼던 테이블을 사용하는게 의도된 풀이라는 사실을 알았다.
이 테이블을 0부터 테이블 길이만큼 각 자리와 xor해주면 새로운 테이블을
얻을 수 있는데 이 테이블이 custom base64 table이었다...
import string,base64
table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
m=[0x08,0x3B,0x01,0x20,0x07,0x34,0x09,0x1F,0x18,0x24,0x13,0x03,0x10,0x38,0x09,0x1B,
0x08,0x34,0x13,0x02,0x08,0x22,0x12,0x03,0x05,0x06,0x12,0x03,0x0F,0x22,0x12,0x17,0x08,
0x01,0x29,0x22,0x06,0x24,0x32,0x24,0x0F,0x1F,0x2B,0x24,0x03,0x15,0x41,0x41]
enc=''.join(table[m[i]-1] for i in range(len(m)))
tmp=[0X30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x5B,0x5C,0x49,0x5F,0x5A,0x56,
0x45,0x58,0x5D,0x43,0x55,0x46,0x52,0x51,0x5F,0x51,0x50,0x50,0x50,0x47,0x46,0x5C,0x76,
0x63,0x6C,0x6E,0x55,0x52,0x43,0x55,0x5C,0x50,0x5F,0x42,0x43,0x5D,0x4F,0x5C,0x54,0x57,
0x55,0x5B,0x5E,0x5E,0x5A,0x4D,0x40,0x5A,0x4C,0x59,0x52,0x50,0x15,0x10]
table2=''.join(chr(tmp[i]^i)for i in range(len(tmp)))
table2+="="
tb=string.maketrans(table2,table)
rb=enc.translate(tb)
print(table)
print(table2)
print(base64.b64decode(rb))
위에서 얻은 테이블을 이용하여 새로 소스를 짜주면
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
0123456789QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm+/=
de1ctf{E_L4nguag3_1s_K3KeK3_N4Ji4}
따로 수정 작업을 거치지 않아도 깔끔하게 플래그가 나오게 된다.
쓸모없는 정보는 없다는것을 다시한번 깨달았다...