[Dreamhack] Permpkin

chrmqgozj·2025년 2월 17일

DreamHack

목록 보기
35/39
  1. main
__int64 __fastcall main(int a1, char **a2, char **a3)
{
  size_t v3; // rbx
  size_t v4; // rbx
  char arr2[32]; // [rsp+0h] [rbp-B0h] BYREF
  char arr[32]; // [rsp+20h] [rbp-90h] BYREF
  char s2[32]; // [rsp+40h] [rbp-70h] BYREF
  char s1[24]; // [rsp+60h] [rbp-50h] BYREF
  FILE *v10; // [rsp+78h] [rbp-38h]
  int v11; // [rsp+84h] [rbp-2Ch]
  FILE *stream; // [rsp+88h] [rbp-28h]
  int v13; // [rsp+90h] [rbp-20h]
  int k; // [rsp+94h] [rbp-1Ch]
  int j; // [rsp+98h] [rbp-18h]
  int i; // [rsp+9Ch] [rbp-14h]

  strcpy(s1, "_this_is_sample_flag_");
  strcpy(s2, "this_is_sample_flag");
  strcpy(arr, "CC2A750B63821F45AC20839");
  for ( i = 0; i <= 22; ++i )
    arr2[i] = convert(arr[i]);
  v13 = strlen(s1);
  swap_string((__int64)s1, 0LL, (unsigned int)(v13 - 1), arr2);
  xor(s1, arr2);
  stream = fopen("rev1.txt", "wb");
  for ( j = 0; ; ++j )
  {
    v3 = j;
    if ( v3 >= strlen(s1) )
      break;
    fprintf(stream, "%d ", (unsigned int)s1[j]);
  }
  fclose(stream);
  v11 = strlen(s2);
  swap_string((__int64)s2, 0LL, (unsigned int)(v11 - 1), arr2);
  xor(s2, arr2);
  v10 = fopen("rev2.txt", "wb");
  for ( k = 0; ; ++k )
  {
    v4 = k;
    if ( v4 >= strlen(s2) )
      break;
    fprintf(v10, "%d ", (unsigned int)s2[k]);
  }
  fclose(v10);
  return 0LL;
}
  1. convert

P~Y: 0~9
F~O: 0~9
<~E: 0~9
그 외: -0X28('(')

  1. swap_string
size_t __fastcall swap_string(char *a1, __int64 a2, __int64 a3, const char *a4)
{
  size_t result; // rax
  int i; // [rsp+2Ch] [rbp-14h]

  for ( i = 0; ; ++i )
  {
    result = strlen(a4);
    if ( i >= result )
      break;
    swap(a1, &a1[a4[i]]);
  }
  return result;
}

s[0]와 s[arr2[i]] swap

  1. xor
__int64 __fastcall xor(const char *a1, const char *a2)
{
  __int64 result; // rax
  signed int v3; // [rsp+14h] [rbp-Ch]
  signed int v4; // [rsp+18h] [rbp-8h]
  int j; // [rsp+1Ch] [rbp-4h]
  signed int k; // [rsp+1Ch] [rbp-4h]
  unsigned int i; // [rsp+1Ch] [rbp-4h]

  v4 = strlen(a2);
  v3 = strlen(a1);
  if ( v3 <= v4 )
  {
    for ( i = 0; ; ++i )
    {
      result = i;
      if ( (int)i >= v3 )
        break;
      a1[i] ^= a2[i];
    }
  }
  else
  {
    for ( j = 0; j < v4; ++j )
      a1[j] ^= a2[j];
    for ( k = v4; ; ++k )
    {
      result = (unsigned int)k;
      if ( k >= v3 )
        break;
      a1[k] ^= a2[k % v4];
    }
  }
  return result;
}

단순 xor

  1. 문제 난이도를 올리는 요소
    arr1이 길이가 23이라고 해서 arr2도 그럴 것이라는 생각을 버려라
    arr2에는 중간에 0x00이 저장되어 있다. 여기가 해당 배열의 끝이다.
    하지만 파이썬으로 해결할 시 0가 저장되어 있어도 숫자 0이기 때문에 NULL로 생각하지 않는다.
    gdb로 까보면 우리가 생각하는 길이와 다른 값이 계속 저장되는 것을 알 수 있다. 이게 힌트다.

솔직히 실수 없는데 왜 자꾸 안 나오지 고민하다가 짜증났는데 gdb에서 값이 이상한 거 보고 내 실수를 깨닫고 행복해졌다.

  1. exploit.py
arr1 = 'CC2A750B63821F45AC20839'
arr2 = []
len_arr2 = 13

for i in range(23):
    if arr1[i].isdigit():
        arr2.append((ord(arr1[i])-ord('('))& 0xff)
    elif arr1[i] > 'E':
        if arr1[i] > 'O':
            if arr1[i] <= 'Y':
                arr2.append((ord(arr1[i]) - ord('P'))& 0xff)
        else:
            arr2.append((ord(arr1[i]) - ord('F'))& 0xff)
    else:
        arr2.append((ord(arr1[i]) - ord('<'))& 0xff)
        
def func1(s):
    for i in range(len_arr2-1, -1, -1):
        s[0], s[arr2[i]] = s[arr2[i]], s[0]
    '''for i in range(len_arr2):
        s[0], s[arr2[i]] = s[arr2[i]], s[0]'''
    
def func2(s):
    if len(s) <= len_arr2:
        for i in range(len(s)):
            s[i] = (s[i] ^ arr2[i]) & 0xff
            
    else:
        for i in range(len(s)):
            s[i] = (s[i] ^ arr2[i%len_arr2]) & 0xff

f1 = open('D:\\code\\dh\\rev\\permpkin\\flag1.txt', 'r')
f2 = open('D:\\code\\dh\\rev\\permpkin\\flag2.txt', 'r')

s1 = f1.read().split()
s2 = f2.read().split()

for i in range(len(s1)):
    s1[i] = int(s1[i])
    
for i in range(len(s2)):
    s2[i] = int(s2[i])
    
func2(s2)
func1(s2)

func2(s1)
func1(s1)

for i in s1:
    print(chr(i),end='')
print()
for i in s2:
    print(chr(i),end='')
print()

0개의 댓글