문제 정보
매우 쉬운 전형적인 reversing문제.
문제 파일
basic_CrackMe/ ├── flag.enc ├── prob └── prob.exe 0 directories, 3 files
flag.enc 암호화된 텍스트 파일,
실행 파일은 flag, flag.exe 각각 리눅스와 윈도우용 둘다 존재한다.
풀이
int __cdecl sub_401500(int a1) { __int64 v1; // rax __int64 v2; // rcx __int64 v3; // rax __int64 v4; // rax int i; // [esp+Ch] [ebp-14h] for ( i = 0; i <= 80; ++i ) { v1 = (Str[i % dword_4054F4] * Str[i % dword_4054F4] + i) ^ *(char *)(i + a1); dword_405040[2 * i] = v1; dword_405044[2 * i] = HIDWORD(v1); LODWORD(v2) = dword_405040[2 * i]; HIDWORD(v2) = dword_405044[2 * i]; v3 = v2 - Str[i % dword_4054F4]; dword_405040[2 * i] = v3; dword_405044[2 * i] = HIDWORD(v3); LODWORD(v2) = dword_405040[2 * i]; HIDWORD(v2) = dword_405044[2 * i]; v4 = v2 + i; dword_405040[2 * i] = v4; dword_405044[2 * i] = HIDWORD(v4); } return 0; }
Str = “have a good day! enjoy wargame!”
dword_4054f4 = Str 문자열 크기,
a1에는 암호화되지 않은 원문 문자열을 나타내는 포인터 주소를 각각 나타낸다.
총 81번을 반복하고 카운트 변수는 i이다.
v1 = (Str[i % 31] * Str[i % 31] + i) ^ a1[i];
v3 = v1 – Str[i % 31];
v4 = v3 + i;
이를 테면,
a1이 “ABCDEFGHIJKLMNOPQRSTUVWXYZ” 문자열이 있다고 가정하자.
이 문자열 크기는 총 26바이트인데,
총 81번 반복하므로 나머지 55바이트(=81-26)는 00 으로 채워진다.
초기에는
v1 = (Str[0 % 31] * Str[0 % 31] + 0) ^ a1[0]
= 0x2A40 ^ 0x41 = 0x2a01
v3 = v1 – Str[0 % 31]
= 0x2a01 – 0x68 = 0x2999
v4 = v3 + 0
= 0x2999
두번째 루프문에서는
v1 = (Str[1 % 31] * Str[1 % 31] + 1) ^ a1[1]
= 0x24c2 ^ 0x42 = 0x2480
v3 = v1 – Str[1 % 31]
= 0x2480 – 0x61 = 0x241f
v4 = 0x241f + 1
= 0x2420
이렇게 암호화된 문자가 하나씩 만들어진다.
암호화시키는 코드를 파이썬으로 구현하면 다음과 같다.
#enc.py def read_file(filename): with open(filename, 'rb+') as file: data = file.read() return data def save_file(filename, data): with open(filename, 'wb+') as file: file.write(data) GDStr = "have a good day! enjoy wargame!" GDStrLen = len(GDStr) filename = 'flag.txt' filecontext = read_file(filename) if(len(filecontext) < 81): filecontext += bytes(81 - len(filecontext)) enc = '' for i in range(81): v1 = (ord(GDStr[i % GDStrLen]) * ord(GDStr[i % GDStrLen]) + i) ^ filecontext[i] v3 = v1 - ord(GDStr[i % GDStrLen]) result = v3 + i enc += hex(result).upper() print(enc) save_file('tmp.enc', enc.encode('utf-8'))
복호화시키는 코드는 역순으로 계산시키면 답이 나온다.
def read_file(filename): with open(filename, 'rb+') as file: data = file.read() return data GDStr = "have a good day! enjoy wargame!" GDStrLen = len(GDStr) filename = 'flag.enc' filecontext = read_file(filename) filecontext = filecontext.decode('utf-8') filecontext = filecontext.split('0X')[1:] filecontext = [int(val, 16) for val in filecontext] dec = '' for i in range(81): v3 = filecontext[i] - i v1 = v3 + ord(GDStr[i % GDStrLen]) v0 = v1 ^ (ord(GDStr[i % GDStrLen]) * ord(GDStr[i % GDStrLen]) + i) print(chr(v0), end='')
FLAG
PS C:\Users\Seo Hyun-gyu\Desktop\basic_CrackMe\test> python3 dec.py Congratulation!: +DH{0h_y0u_6ot_cr4ck_m3_4nd_h4ve_good_d4y~}+ good luck new year!
DH{0h_y0u_6ot_cr4ck_m3_4nd_h4ve_good_d4y~}