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)