__int64 __fastcall main(int a1, char **a2, char **a3)
{
int v3; // eax
int i; // [rsp+4h] [rbp-8Ch]
_BYTE *ptr; // [rsp+8h] [rbp-88h]
char s[104]; // [rsp+10h] [rbp-80h] BYREF
unsigned __int64 v8; // [rsp+78h] [rbp-18h]
v8 = __readfsqword(0x28u);
ptr = malloc(0x64uLL);
fgets(s, 100, stdin);
s[strcspn(s, "\n")] = 0;
v3 = strlen(s);
encrypt(ptr, s, v3);
for ( i = 0; i < strlen(s); ++i )
printf("%02hhx", (unsigned int)(char)ptr[i]);
free(ptr);
return 0LL;
}
unsigned __int64 __fastcall encrypt(_BYTE *a1, char *a2, int a3)
{
int v3; // eax
int v4; // edx
unsigned __int64 result; // rax
char *v6; // rax
char v7; // cl
_BYTE *v8; // rax
char *v9; // rax
char v10; // cl
_BYTE *v11; // rax
char *v12; // rax
char v13; // cl
_BYTE *v14; // rax
char *v15; // rax
char v16; // cl
_BYTE *v17; // rax
char *v18; // rax
char v19; // cl
_BYTE *v20; // rax
char *v21; // rax
char v22; // cl
_BYTE *v23; // rax
char *v24; // rax
char v25; // cl
_BYTE *v26; // rax
char *v27; // rax
char v28; // cl
int v32; // [rsp+20h] [rbp-4h]
v3 = a3 + 7;
v4 = a3 + 14;
if ( v3 < 0 )
v3 = v4;
v32 = v3 >> 3;
result = (unsigned int)(a3 % 8);
switch ( (int)result )
{
case 0:
goto LABEL_4;
case 1:
goto LABEL_11;
case 2:
goto LABEL_10;
case 3:
goto LABEL_9;
case 4:
goto LABEL_8;
case 5:
goto LABEL_7;
case 6:
goto LABEL_6;
case 7:
while ( 1 )
{
v9 = a2++;
v10 = *v9;
v11 = a1++;
*v11 = v10 ^ 0x66;
LABEL_6:
v12 = a2++;
v13 = *v12;
v14 = a1++;
*v14 = v13 ^ 0x44;
LABEL_7:
v15 = a2++;
v16 = *v15;
v17 = a1++;
*v17 = v16 ^ 0x11;
LABEL_8:
v18 = a2++;
v19 = *v18;
v20 = a1++;
*v20 = v19 ^ 0x77;
LABEL_9:
v21 = a2++;
v22 = *v21;
v23 = a1++;
*v23 = v22 ^ 0x55;
LABEL_10:
v24 = a2++;
v25 = *v24;
v26 = a1++;
*v26 = v25 ^ 0x22;
LABEL_11:
v27 = a2++;
v28 = *v27;
result = (unsigned __int64)a1++;
*(_BYTE *)result = v28 ^ 0x33;
if ( --v32 <= 0 )
break;
LABEL_4:
v6 = a2++;
v7 = *v6;
v8 = a1++;
*v8 = v7 ^ 0x88;
}
break;
default:
return result;
}
return result;
}
a1: ptr(output), a2: s(input), a3: s의 길이
a3의 길이를 8로 나눈 나머지에 따라 switch문을 통과한다.
그대로 구현하면 된다.
각 label이 복잡해보이지만 잘 보면 모두 일정한 형태를 띄고 있다.
s[i]에 어떤 값을 xor해서 ptr에 저장한다. 즉 output을 읽어서 같은 값을 한 번더 xor 해주면 플래그를 얻을 수 있다.
printf("%02hhx", (unsigned int)(char)ptr[i]);
idx값을 다 넣어봐도 멀쩡한 플래그가 안 나와서 다시 코드를 살펴보니 각 문자가 하나의 플래그 문자를 뜻하는게 아니라 2개가 세트로 16진수를 나타내고 있다는 걸 알게 되었다.
arr = [0x66, 0x44, 0x11, 0x77, 0x55, 0x22, 0x33, 0x88]
flag = ''
with open('D:\\code\\dh\\rev\\legacyopt\\output.txt', 'r') as f:
data = f.read()
size = len(data)
idx = 7-((size//2)%8)
for i in range(0, size, 2):
h = int(data[i:i+2], 16)
flag += chr((h^arr[idx]) & 0xff)
idx = (idx+1) % 8
print(flag)
-> DH{Duffs_Device_but_use_memcpy_instead}