__int64 __fastcall main(int a1, char **a2, char **a3)
{
char ptr; // [rsp+Bh] [rbp-25h] BYREF
int v5; // [rsp+Ch] [rbp-24h]
_BYTE *v6; // [rsp+10h] [rbp-20h]
FILE *stream; // [rsp+18h] [rbp-18h]
FILE *s; // [rsp+20h] [rbp-10h]
unsigned __int64 v9; // [rsp+28h] [rbp-8h]
v9 = __readfsqword(0x28u);
v6 = &unk_2004;
stream = fopen("flag.png", "rb");
if ( !stream )
{
puts("fopen() error");
exit(1);
}
s = fopen("encrypted", "wb");
if ( !s )
{
puts("fopen() error");
fclose(stream);
exit(1);
}
v5 = 0;
while ( fread(&ptr, 1u, 1u, stream) == 1 )
{
ptr ^= v6[v5 % 4];
ptr += 19;
fwrite(&ptr, 1u, 1u, s);
++v5;
}
fclose(stream);
fclose(s);
return 0;
}
stream과 s가 비어있는지 확인한다
enc에서 1바이트씩 읽어서 ptr에 저장후 읽을게 있으면 계속 반복
ptr을 xor v6에 0,1,2,3번째 있는 값들로 돌림xor을 해주고 19를 더한다
int main() {
unsigned char table[4] = {0xDE, 0xAD, 0xBE, 0xEF};
unsigned char ptr;
FILE *enc = fopen("encrypted", "rb");
FILE *flag = fopen("flag.png", "wb");
if(!enc || !flag) return 1;
int v5 = 0;
while ( fread(&ptr, 1u, 1u, enc) == 1 )
{
ptr -= 19;
ptr ^= table[v5 % 4];
fwrite(&ptr, 1u, 1u, flag);
++v5;
}
fclose(flag);
fclose(enc);
return 0;
}
역으로 해서 파일들이 있는 디렉토리에서 컴파일 해준다

후후후 flag.png를 explorer.exe로 열어서 확인한다면?


int __fastcall main(int argc, const char **argv, const char **envp)
{
int i; // [rsp+4h] [rbp-12Ch]
_QWORD v5[5]; // [rsp+10h] [rbp-120h]
_BYTE v6[11]; // [rsp+38h] [rbp-F8h]
__int64 v7; // [rsp+43h] [rbp-EDh]
char s[8]; // [rsp+50h] [rbp-E0h] BYREF
__int64 v9; // [rsp+58h] [rbp-D8h]
__int64 v10; // [rsp+60h] [rbp-D0h]
__int64 v11; // [rsp+68h] [rbp-C8h]
__int64 v12; // [rsp+70h] [rbp-C0h]
__int64 v13; // [rsp+78h] [rbp-B8h]
__int64 v14; // [rsp+80h] [rbp-B0h]
__int64 v15; // [rsp+88h] [rbp-A8h]
__int64 v16; // [rsp+90h] [rbp-A0h]
__int64 v17; // [rsp+98h] [rbp-98h]
__int64 v18; // [rsp+A0h] [rbp-90h]
__int64 v19; // [rsp+A8h] [rbp-88h]
int v20; // [rsp+B0h] [rbp-80h]
char dest[8]; // [rsp+C0h] [rbp-70h] BYREF
__int64 v22; // [rsp+C8h] [rbp-68h]
__int64 v23; // [rsp+D0h] [rbp-60h]
__int64 v24; // [rsp+D8h] [rbp-58h]
__int64 v25; // [rsp+E0h] [rbp-50h]
__int64 v26; // [rsp+E8h] [rbp-48h]
__int64 v27; // [rsp+F0h] [rbp-40h]
__int64 v28; // [rsp+F8h] [rbp-38h]
__int64 v29; // [rsp+100h] [rbp-30h]
__int64 v30; // [rsp+108h] [rbp-28h]
__int64 v31; // [rsp+110h] [rbp-20h]
__int64 v32; // [rsp+118h] [rbp-18h]
int v33; // [rsp+120h] [rbp-10h]
unsigned __int64 v34; // [rsp+128h] [rbp-8h]
v34 = __readfsqword(0x28u);
v5[0] = 0xC313A0A11150D18LL;
v5[1] = 0x2C37426D44472F19LL;
v5[2] = 0x1B1A3A1704000F00LL;
v5[3] = 0x1301263B1904312ALL;
v5[4] = 0x361F06041A0A3E17LL;
*(_DWORD *)v6 = 738656770;
*(_QWORD *)&v6[3] = 0x2C1018043E1C3E2CLL;
v7 = 0x1F0004160A151F2BLL;
*(_QWORD *)s = 0;
v9 = 0;
v10 = 0;
v11 = 0;
v12 = 0;
v13 = 0;
v14 = 0;
v15 = 0;
v16 = 0;
v17 = 0;
v18 = 0;
v19 = 0;
v20 = 0;
*(_QWORD *)dest = 0;
v22 = 0;
v23 = 0;
v24 = 0;
v25 = 0;
v26 = 0;
v27 = 0;
v28 = 0;
v29 = 0;
v30 = 0;
v31 = 0;
v32 = 0;
v33 = 0;
printf("Input : ");
__isoc99_scanf("%59s", s);
if ( strlen(s) == 59 )
{
strcpy(dest, s);
for ( i = 0; i <= 58; ++i )
dest[i] ^= *((_BYTE *)v5 + i);
if ( !strcmp(dest, "Please_input_the_correct_new_year_greetings_at_this_problem") )
printf("Correct! Flag is DH{%s}\n", s);
else
puts("Wrong!");
}
else
{
puts("Wrong!");
}
return 0;
}
59글자 플래그를 입력받으면 Correct와 플래그출력
v5[0] = 0xC313A0A11150D18LL; v5[1] = 0x2C37426D44472F19LL; v5[2] = 0x1B1A3A1704000F00LL; v5[3] = 0x1301263B1904312ALL; v5[4] = 0x361F06041A0A3E17LL; *(_DWORD *)v6 = 738656770; *(_QWORD *)&v6[3] = 0x2C1018043E1C3E2CLL; v7 = 0x1F0004160A151F2BLL; *(_QWORD *)s = 0; v9 = 0; v10 = 0; v11 = 0; v12 = 0; v13 = 0; v14 = 0; v15 = 0; v16 = 0; v17 = 0; v18 = 0; v19 = 0; v20 = 0; *(_QWORD *)dest = 0;v5주소부터 리틀엔디안으로 저장된 값들과 xor을 해서 나오는 값을 저 길다란 문자열과 한글자씩 비교한다
import struct
>>> key = b""
>>> key += struct.pack('<Q', 0xC313A0A11150D18)
>>> key += struct.pack('<Q', 0x2C37426D44472F19)
>>> key += struct.pack('<Q', 0x1B1A3A1704000F00)
>>> key += struct.pack('<Q', 0x1301263B1904312A)
>>> key += struct.pack('<Q', 0x361F06041A0A3E17)
>>> key += b"\x02\x02\x07"
>>> key += struct.pack('<Q', 0x2C1018043E1C3E2C)
>>> key += struct.pack('<Q', 0x1F0004160A151F2B)
>>> target="Please_input_the_correct_new_year_greetings_at_this_problem"
>>> flag =""
>>> for i in range(59):
... flag+=chr((ord(target[i]) ^ key[i]) & 0xFF)
...
>>> print(flag)
python에 있는 모듈로 리틀엔디안 저장 방식을 배열로 만든뒤 하나하나 나와있는 문자열과 xor을 해주면 flag가 나온다

v7 = 0;
v6 = 0;
v11 = 0;
initialize();
buf = malloc(69u);
fd = open("./flag", 0);
read(fd, buf, 0x45u);
close(fd);
/// buf에 플래그
get_rand_num(&v6);
printf("Random number: %#x\n", v6);
printf("Input? ");
__isoc99_scanf("%d", &v7);
/// v7 d입력받기
v11 = v6 ^ v7;
snprintf(s, 9u, "%08x", v6 ^ v7);
for ( i = 0; i <= 7; ++i )
s1[i] = s[7 - i];
printf("Result: %s\n", s1);
s2 = "a0b4c1d7";
if ( !strcmp(s1, "a0b4c1d7") )
{
puts("Congrats!");
puts((const char *)buf);
}
else
{
puts("Try again");
}
return 0;
}
입력 ^ rand => 거꾸로 = a0b4c1d7


거꾸로하고 xor해준값을 입력한다

__int64 __fastcall main(int a1, char **a2, char **a3)
{
int v4; // [rsp+8h] [rbp-18h]
char s1[8]; // [rsp+Fh] [rbp-11h] BYREF
char v6; // [rsp+17h] [rbp-9h]
unsigned __int64 v7; // [rsp+18h] [rbp-8h]
v7 = __readfsqword(0x28u);
*(_QWORD *)s1 = 0;
v6 = 0;
v4 = 0;
do
{
printf("What is your favorite fruit?\n> ");
__isoc99_scanf("%10sbanana", s1);
if ( !strcmp(s1, "banana") )
{
puts("I also like banana.");
if ( (v4 & 1) == 0 )
{
v4 |= 1u;
sub_11E9("banana");
}
}
else if ( !strcmp(s1, "strawberry") )
{
puts("Strawberries! Great choice.");
if ( (v4 & 2) == 0 )
{
v4 |= 2u;
sub_11E9("strawberry");
}
}
else if ( !strcmp(s1, "erwin") )
{
puts("I never heard of it, but it looks delicious.");
if ( (v4 & 4) == 0 )
{
v4 |= 4u;
sub_11E9("erwin");
}
}
else if ( !strcmp(s1, "mandarin") )
{
puts("It's so sour...");
if ( (v4 & 8) == 0 )
{
v4 |= 8u;
sub_11E9("mandarin");
}
}
else if ( !strcmp(s1, "melon") )
{
puts("I wanna eat it with jamon.");
if ( (v4 & 0x10) == 0 )
{
v4 |= 0x10u;
sub_11E9("melon");
}
}
else
{
puts("Ew, I don't like it.");
}
}
while ( v4 != 31 );
printf("Here is the flag: %s\n", a0);
return 0;
}
입력을 받고 과일에 따라 다른 대답을 해주나 보다
하지만 딸기는 길이가 10이라 입력이 9까지밖에 안되서 못 읽는다

패치를 10까지 받을 수 있도록 online binary hex 에디터를 이용해 맛있게 해준다

뭔가 마음에 들지 않지만 작동만 잘 해준다면야

야호

실행해보자

오이런

저걸 띄우는 것들인 것 같다
sub_1400032F0을 보자

중간에 있는 sub_140002C40이 무언가 수상하다

오옹

jackpot
함수의 return을 0으로 해서 함수의 팔다리를 절단해보자

hex에서 본 첫번째 위치이다
xor eax,eax로 eax를 0으로 만들고
ret를 하는 것은 31 C0 C3 90 90 (90은 nop : no operation 계산안해서 밀리거나 그런거 없게 해준다)
으로 패치해준다음 실행한다면

(가리긴 했는데 안그려져서 플래그가 나온다)

