https://buuoj.cn/challenges#rip
nc 发现可以输入字符,然后得到返回
https://blog.csdn.net/qq_45691294/article/details/110959284
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX unknown - GNU_STACK missing
PIE: No PIE (0x400000)
Stack: Executable
RWX: Has RWX segments
这里什么都没开
gets 没有限制输入,存在 栈溢出 的漏洞,在字符串表里面发现了 /bin/sh
的字符,可以通过将 fun 函数的地址覆盖到返回地址就可以实现获得系统权限
双击 s 查看 s 在栈上的位置
-0000000000000010 ; D/A/* : change type (data/ascii/array)
-0000000000000010 ; N : rename
-0000000000000010 ; U : undefine
-0000000000000010 ; Use data definition commands to create local variables and function arguments.
-0000000000000010 ; Two special fields " r" and " s" represent return address and saved registers.
-0000000000000010 ; Frame size: 10; Saved regs: 8; Purge: 0
-0000000000000010 ;
-0000000000000010
-0000000000000010 db ? ; undefined
-000000000000000F s db ?
-000000000000000E db ? ; undefined
-000000000000000D db ? ; undefined
-000000000000000C db ? ; undefined
-000000000000000B db ? ; undefined
-000000000000000A db ? ; undefined
-0000000000000009 db ? ; undefined
-0000000000000008 db ? ; undefined
-0000000000000007 db ? ; undefined
-0000000000000006 db ? ; undefined
-0000000000000005 db ? ; undefined
-0000000000000004 db ? ; undefined
-0000000000000003 db ? ; undefined
-0000000000000002 db ? ; undefined
-0000000000000001 db ? ; undefined
+0000000000000000 s db 8 dup(?)
+0000000000000008 r db 8 dup(?)
+0000000000000010
+0000000000000010 ; end of stack variables
Two special fields ” r” and ” s” represent return address and saved registers.
-
rame size: 10:这是指当前函数调用的栈帧大小为 10 个单位(通常是字节)。栈帧是函数调用时在栈上分配的一块内存,用于存储局部变量、返回地址和其他信息。
-
Saved regs: 8:这是指在当前函数调用中保存了 8 个寄存器的值。寄存器是处理器中的高速存储单元,用于临时存储数据。保存寄存器的值是为了在函数调用结束后能够恢复这些寄存器的原始值。
-
Purge: 0:这是指在当前函数调用中没有清除(purge)任何参数或数据。清除操作通常用于释放不再需要的内存或资源。
栈如果要想象的话还是用一个下拉的帘子比较好想,或者是一个可伸缩的水桶,伸缩的方式是调整底部(像手风琴一样往下拉或者往上推),填写数据的时候就像往里面加水,如果没有限制水就会往上漫覆盖掉上面的东西
这里上面有什么呢?怎么确定倒多少水怎么样的水才能达到跳转到 fun 的目的呢?
通过查看栈,发现需要填充 15 字节的无意义数据,填充 8 个字节的 s(也就是 bp 的值),然后就是我们想要修改的 8 个字节的 r 的值
于是用 python 的 pwn 库编写 exp
修改 r 的值的时候,这里有一个坑:调用 system 的时候会检测栈区有没有对齐 → 栈区对齐
如果正常调用 fun 的话,在调用 system 的时候 sp 此时是这个状态
RBP 0x7fff09fd1718 ◂— 'aeaaafaa'
RSP 0x7fff09fd1718 ◂— 'aeaaafaa'
*RIP 0x401191 (fun+11) ◂— call 0x401040
所以在进入 fun 的时候要跳过 push ebp,把栈对齐了
因此编写 exp: