PWN-0x02 ROP
Return Oriented Programming
eg.ret2shellcode & ret2libc
开启NX(No-eXecute)保护则堆栈不可执行
vmap看权限
动态链接-dynamically linked
静态链接-statically linked
0x01 系统调用
32bit: int 0x80
64bit: system call
sys_execve;sys_write;sys_read;sys_open;sys_close.
execve(“/bin/sh”,0,0) == system(“/bin/sh”)
eax<-0x0b == sys_execve(ebx,ecx,edx)
0x02 Shellcode生成机制
asm(shellcraft.i386.linux.sh(),arch=’i386’,os=’linux’)
tip: 这是pwntools自带的,有的题目(比如有长度限制的)会不可用。
payload = shellcode.ljust( int len(偏移) , chr (垃圾字节) )
0x03 PLT表&GOT表的机制
PLT(Procedure Linkage Table)程序链接表。它有两个功能,要么在 .got.plt
节中拿到地址,并跳转。要么当 .got.plt
没有所需地址的时,触发「链接器」去找到所需地址
1 | 1 jmp DWORD PTR ds:&addr(一个函数) #进入堆栈前为下一条命令的地址 |
GOT(Global Offset Table)全局偏移表。这是「链接器」为「外部符号」填充的实际偏移表。
PLT表中的数据就是GOT表中的一个地址 ,基本上是一一对应的,但GOT[1]和GOT[2]被PLT[0]利用 ,所以
PLT表中的每一项的数据内容都是对应的GOT表中一项的地址这个是固定不变的, PLT表中的数据根本不是函数的真实地址,而是GOT表项的地址。 进入带有@plt标志的函数时,这个函数其实就是个过渡作用,因为GOT表项中的数据才是函数最终的地址,而PLT表中的数据又是GOT表项的地址,我们就可以通过PLT表跳转到GOT表来得到函数真正的地址。
0x04 伪造栈帧
PLT表具有如下结构,和正常函数无异
1 | pop |
1 | aaa |
func_addr == libc_base + func_offset ==> 找基址,找到库的基址,库内别的函数的地址就都知道了
libc_version=LibcSearcher(‘Func’,Func_addr)
注意libc库的版本,不同版本的ubuntu所用的libc也不同