728x90
실행 화면
- IDA를 사용하여 분석하기
main에 들어가보면 I love pancakes 문자배열이 들어가 있다.
- Pseudocode-A를 확인해 보면 실행 코드르 확인할 수 있다.
int __cdecl main(int argc, const char **argv, const char **envp)
{
int i; // [rsp+0h] [rbp-20A0h]
int v6; // [rsp+4h] [rbp-209Ch]
__int64 v7[16]; // [rsp+10h] [rbp-2090h] BYREF
char s[18]; // [rsp+90h] [rbp-2010h] BYREF
__int16 v9; // [rsp+A2h] [rbp-1FFEh]
int v10; // [rsp+A4h] [rbp-1FFCh]
__int64 v11; // [rsp+A8h] [rbp-1FF8h]
char v12[4064]; // [rsp+B0h] [rbp-1FF0h] BYREF
char v13[4104]; // [rsp+1090h] [rbp-1010h] BYREF
unsigned __int64 v14; // [rsp+2098h] [rbp-8h]
v14 = __readfsqword(0x28u);
// V7 배열에는 I love pancakes 가 들어있다.
v7[0] = 73LL;
v7[1] = 32LL;
v7[2] = 108LL;
v7[3] = 111LL;
v7[4] = 118LL;
v7[5] = 101LL;
v7[6] = 32LL;
v7[7] = 112LL;
v7[8] = 97LL;
v7[9] = 110LL;
v7[10] = 99LL;
v7[11] = 97LL;
v7[12] = 107LL;
v7[13] = 101LL;
v7[14] = 115LL;
// s 변수에는 Betaflash_is_slow 문자열이 복사되어 들어있다.
strcpy(s, "Betaflash_is_slow");
v9 = 0;
v10 = 0;
v11 = 0LL;
memset(v12, 0, sizeof(v12));
puts("We are under attack.");
puts("We need a group of hacker to decrypt this weird message.");
puts("And Betaflash is not slow :)).");
// encrypt 함수로 s변수와 v7 변수로 보낸다.
encrypt(s, 10LL, (__int64)v7);
// 암호화된 데이터를 출력한다.
v6 = strlen(s);
for ( i = 0; i < v6; ++i )
sprintf(&v13[2 * i], "%02X", (unsigned __int8)s[i]);
v13[2 * i] = 0;
printf("Decrypt me if you can: %s\n", v13);
return __readfsqword(0x28u) ^ v14;
}
- encrypt 함수 코드
__int64 __fastcall encrypt(_QWORD *a1, __int64 a2, __int64 a3)
{
__int64 result; // rax
unsigned __int64 *v4; // rax
__int64 v5; // rcx
__int64 v6; // rax
unsigned __int64 v7; // [rsp+20h] [rbp-38h]
unsigned __int64 v8; // [rsp+28h] [rbp-30h]
__int64 i; // [rsp+30h] [rbp-28h]
__int64 v10; // [rsp+38h] [rbp-20h]
__int64 v11; // [rsp+50h] [rbp-8h]
v7 = a1[a2 - 1]; // 입력 배열의 마지막 요소
v8 = 0LL; // 초기화
result = 2654435769LL;
if ( a2 > 1 )
{
v10 = 52 / a2 + 6;
while ( 1 )
{
v6 = v10--;
if ( v6 <= 0 )
break;
v8 += 2654435769LL;
v11 = (v8 >> 2) & 3; // v8을 오른쪽으로 2비트 시프트한 후 3으로 나눈 나머지 값의 결과를 v11에 할당
for ( i = 0LL; i < a2 - 1; ++i )
{
v4 = &a1[i];
*v4 += (((4LL * a1[i + 1]) ^ (v7 >> 5)) + ((a1[i + 1] >> 3) ^ (16 * v7))) ^ ((a1[i + 1] ^ v8)
+ (v7 ^ *(_QWORD *)(8 * (v11 ^ i & 3) + a3)));
v7 = *v4;
}
// 마지막 요소의 위치 계산, (_QWORD *)((char*)a1 + v5) 는 마지막 요소의 위치를 표시
// ((4LL**a1)^ 부부는 *a1을 여러 변수들과 조합하여 암호화 한다.
v5 = 8 * a2 - 8;
*(_QWORD *)((char *)a1 + v5) += (((4LL * *a1) ^ (v7 >> 5)) + ((*a1 >> 3) ^ (16 * v7))) ^ ((*a1 ^ v8)
+ (v7 ^ *(_QWORD *)(8 * (v11 ^ i & 3) + a3)));
v7 = *(_QWORD *)((char *)a1 + v5);
}
return 0LL;
}
return result;
}
- exploit 코드
import numpy as np
uint64 = np.uint64
enc = []
key = [uint64(ord(x)) for x in 'I love pancakes\x00']
ct = 'D0A4AE4DCC99E368BABD66996D67B88159ABE2D022B0AD78F1D69A6EB1E81CF3589B3EFE994005D6A9DE9DB2FD3C44B77628D2316AAC2229E938EC932BE42220DD6D1D914655820A43C09E2236993A8D'
for i in range(0, len(ct), 16):
enc.append(
uint64(int(bytes.fromhex(ct[i:i+16])[::-1].hex(),16))
)
v8 = uint64(0)
for i in range(11):
v8 += uint64(0x9E3779B9)
for _ in range(11):
v11 = (v8 >> uint64(2)) & uint64(3)
for i in range(9,-1,-1):
v7 = enc[(i-1)%10]
enc[i] -= (((uint64(4) * enc[(i+1)%10]) ^ (v7 >> uint64(5))) + ((enc[(i+1)%10] >> uint64(3)) ^ (uint64(16) * v7))) ^ ((enc[(i+1)%10] ^ v8) + (v7 ^ key[v11 ^ uint64(i) & uint64(3)]))
v8 -= uint64(0x9E3779B9)
flag = b''.join([bytes.fromhex(hex(x)[2:])[::-1] for x in enc if x != 0])
print(flag)
'S-DEV > 패커 제작' 카테고리의 다른 글
Reverse Engineering (0) | 2023.08.29 |
---|---|
codeengn (0) | 2023.08.24 |