본문 바로가기

S-DEV/패커 제작

Tiny Encryption Algorithm

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