C 请帮助我理解这个main()代码
请有人帮我了解一下这里发生了什么事。实际上是在主程序上C 请帮助我理解这个main()代码,c,shellcode,C,Shellcode,请有人帮我了解一下这里发生了什么事。实际上是在主程序上 #include <stdlib.h> char shellcode[] = "\xbb\x14\x00\x00\x00", "\xb8\x01\x00\x00\x00","\xcd\x00"; int main() { int *ret ret = (int *) &ret + 2; (*ret) = (int)shellcode; } #包括 字符外壳代码[]=“\xbb\x14\x00
#include <stdlib.h>
char shellcode[] = "\xbb\x14\x00\x00\x00", "\xb8\x01\x00\x00\x00","\xcd\x00";
int main()
{
int *ret
ret = (int *) &ret + 2;
(*ret) = (int)shellcode;
}
#包括
字符外壳代码[]=“\xbb\x14\x00\x00\x00”、“\xb8\x01\x00\x00\x00\x00”、“\xcd\x00”;
int main()
{
内特*内特
ret=(int*)&ret+2;
(*ret)=(int)外壳代码;
}
首先是一些让代码正常工作的修复:
- 追加至第7行以标记指令的结束
- 删除第3行中第一个字符串之后的其他字符串,因为此指令行希望分配给char变量
stdlib
是不需要的,因为它没有使用任何内容,直接使用第8行中的结果可以跳过对ret
的赋值,并且您的shellcode
字符串可以缩短为3个字符,因为只使用了4个字节,C字符串以终止字符结尾
char shellcode[] = "\xbb\x14\x00";
int main()
{
int *ret;
*((int*)&ret + 2) = (int)shellcode;
}
在汇编之后,使用针对x86目标输出的gcc-o test.o-c test.c
编译此文件(附带我的注释):
节的反汇编。文本:
00000000 : ; int main(){
0:55推送%ebp;将基本指针保存在堆栈上
1:89 e5 mov%esp,%ebp;将当前堆栈保存在基本指针中
3:83 e4 f0和$0xfffffff0,%esp;按16对齐堆栈
6:83 ec 10 sub$0x10,%esp;在堆栈上保留16个字节(包括)
9:e8 00调用e;只需向前移动程序指针,即可对齐以下指令
e:8d 44 24 0c lea 0xc(%esp),%eax;%eax=&ret
12:83 C008添加$0x8,%eax;%eax=(int*)%eax+2
15:ba 00 mov$0x0,%edx;%edx=(int)外壳代码
1a:89 10 mov%edx,(%eax);*(%eax)=%edx
1c:c9离开;从enter恢复堆栈和基指针
1d:c3 ret;}
1e:90无
1f:90无
分解截面。数据:
00000000 :
0:bb.字节0xbb;字符外壳代码[]=“\xbb。。。
1:14 00 adc$0x0,%al;..\x14\x00。。。
... ; ..."; (应该是终止字符\x00)
假设堆栈对齐不起任何作用,您的4个外壳代码
字节将被复制到ret
后面的堆栈和保存的基指针上,因此超出了函数范围。
现在考虑一下
int main()
是int main(int argc,char**argv)的一个快捷方式
可以得出结论:这4个字节替换argv
——在main中传递的命令行字符串的地址被覆盖。但是为什么呢?它不会编译,因为int*ret
;-)后面缺少分号Sems将成为一个系统黑客。程序在没有返回指令的情况下将外壳代码字节写入堆栈并退出main,这是未定义的行为;他们为什么要使用支架?他们不可能把它写成ret=(int)外壳代码;括号冗长且无用,但代码可能是*ret=(int)ShellCode我们在声明指针时使用*ret,然后在将变量地址分配给ret指针时使用ret=&变量,然后在尝试访问ret指针内的值时再次使用*ret。。。我说的对吗?哇!这有点让人不知所措,但我认为这个想法是为了覆盖eip以指向shell代码或其他东西,我在学习汇编时遇到了问题,因为我使用的是x86_64 Linux,而且几乎没有一本好书可以给我提供实践教程
Disassembly of section .text:
00000000 <_main>: ; int main(){
0: 55 push %ebp ; save base pointer on stack
1: 89 e5 mov %esp,%ebp ; save current stack in base pointer
3: 83 e4 f0 and $0xfffffff0,%esp ; align stack by 16
6: 83 ec 10 sub $0x10,%esp ; reserve 16 bytes on stack (including <int *ret;>)
9: e8 00 00 00 00 call e <_main+0xe> ; just move program pointer forward for the following instruction to be aligned
e: 8d 44 24 0c lea 0xc(%esp),%eax ; %eax = &ret
12: 83 c0 08 add $0x8,%eax ; %eax = (int*)%eax + 2
15: ba 00 00 00 00 mov $0x0,%edx ; %edx = (int)shellcode
1a: 89 10 mov %edx,(%eax) ; *(%eax) = %edx
1c: c9 leave ; restore stack & base pointer from enter
1d: c3 ret ; }
1e: 90 nop
1f: 90 nop
Disassembly of section .data:
00000000 <_shellcode>:
0: bb .byte 0xbb ; char shellcode[] = "\xbb...
1: 14 00 adc $0x0,%al ; ...\x14\x00...
... ; ..."; (should be the termination character \x00)