LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 713|回复: 3

请问斑竹这应该学习啥书?

[复制链接]
发表于 2004-5-8 12:57:09 | 显示全部楼层 |阅读模式

  1. 1. vi shellcode.c

  2. #include
  3. int main ( int argc, char * argv[] )
  4. {
  5.     char * name[2];
  6.     name[0] = "/bin/ksh";
  7.     name[1] = NULL;
  8.     execve( name[0], name, NULL );
  9.     return 0;
  10. }

  11. 2. gcc -o shellcode -ggdb -static shellcode.c

  12. 3. gdb shellcode

  13. [scz@ /home/scz/src]> gdb shellcode
  14. GNU gdb 4.17.0.11 with Linux support
  15. This GDB was configured as "i386-redhat-linux"...
  16. (gdb) disassemble main <-- -- -- 输入
  17. Dump of assembler code for function main:
  18. 0x80481a0 :       pushl  %ebp
  19. 0x80481a1 :     movl   %esp,%ebp
  20. 0x80481a3 :     subl   $0x8,%esp
  21. 0x80481a6 :     movl   $0x806f308,0xfffffff8(%ebp)
  22. 0x80481ad :    movl   $0x0,0xfffffffc(%ebp)
  23. 0x80481b4 :    pushl  $0x0
  24. 0x80481b6 :    leal   0xfffffff8(%ebp),%eax
  25. 0x80481b9 :    pushl  %eax
  26. 0x80481ba :    movl   0xfffffff8(%ebp),%eax
  27. 0x80481bd :    pushl  %eax
  28. 0x80481be :    call   0x804b9b0 <__execve>
  29. 0x80481c3 :    addl   $0xc,%esp
  30. 0x80481c6 :    xorl   %eax,%eax
  31. 0x80481c8 :    jmp    0x80481d0
  32. 0x80481ca :    leal   0x0(%esi),%esi
  33. 0x80481d0 :    leave
  34. 0x80481d1 :    ret
  35. End of assembler dump.
  36. (gdb) disas __execve <-- -- -- 输入
  37. Dump of assembler code for function __execve:
  38. 0x804b9b0 <__execve>:   pushl  %ebx
  39. 0x804b9b1 <__execve+1>: movl   0x10(%esp,1),%edx
  40. 0x804b9b5 <__execve+5>: movl   0xc(%esp,1),%ecx
  41. 0x804b9b9 <__execve+9>: movl   0x8(%esp,1),%ebx
  42. 0x804b9bd <__execve+13>:        movl   $0xb,%eax
  43. 0x804b9c2 <__execve+18>:        int    $0x80
  44. 0x804b9c4 <__execve+20>:        popl   %ebx
  45. 0x804b9c5 <__execve+21>:        cmpl   $0xfffff001,%eax
  46. 0x804b9ca <__execve+26>:        jae    0x804bcb0 <__syscall_error>
  47. 0x804b9d0 <__execve+32>:        ret
  48. End of assembler dump.

  49. 4. 研究 main() 函数的汇编代码

  50. 0x80481a0 :       pushl  %ebp      # 保存原来的栈基指针
  51.                                          # 栈基指针与堆栈指针不是一个概念
  52.                                          # 栈基指针对应栈底,堆栈指针对应栈顶
  53. 0x80481a1 :     movl   %esp,%ebp # 修改得到新的栈基指针
  54.                                          # 与我们以前在dos下汇编格式不一样
  55.                                          # 这个语句是说把esp的值赋给ebp
  56.                                          # 而在dos下,正好是反过来的,一定要注意
  57. 0x80481a3 :     subl   $0x8,%esp # 堆栈指针向栈顶移动八个字节
  58.                                          # 用于分配局部变量的存储空间
  59.                                          # 这里具体就是给 char * name[2] 预留空间
  60.                                          # 因为每个字符指针占用4个字节,总共两个指针
  61. 0x80481a6 :     movl   $0x806f308,0xfffffff8(%ebp)
  62.                                          # 将字符串"/bin/ksh"的地址拷贝到name[0]
  63.                                          # name[0] = "/bin/ksh";
  64.                                          # 0xfffffff8(%ebp) 就是 ebp - 8 的意思
  65.                                          # 注意堆栈的增长方向以及局部变量的分配方向
  66.                                          # 先分配name[0]后分配name[1]的空间
  67. 0x80481ad :    movl   $0x0,0xfffffffc(%ebp)
  68.                                          # 将NULL拷贝到name[1]
  69.                                          # name[1] = NULL;
  70. 0x80481b4 :    pushl  $0x0
  71.                                          # 按从右到左的顺序将execve()的三个参数依次压栈
  72.                                          # 首先压入 NULL (第三个参数)
  73.                                          # 注意pushl将压入一个四字节长的0
  74. 0x80481b6 :    leal   0xfffffff8(%ebp),%eax
  75.                                          # 将 ebp - 8 本身放入eax寄存器中
  76.                                          # leal的意思是取地址,而不是取值
  77. 0x80481b9 :    pushl  %eax      # 其次压入 name
  78. 0x80481ba :    movl   0xfffffff8(%ebp),%eax
  79. 0x80481bd :    pushl  %eax      # 将 ebp - 8 本身放入eax寄存器中
  80.                                          # 最后压入 name[0]
  81.                                          # 即 "/bin/ksh" 字符串的地址
  82. 0x80481be :    call   0x804b9b0 <__execve>
  83.                                          # 开始调用 execve()
  84.                                          # call指令首先会将返回地址压入堆栈
  85. 0x80481c3 :    addl   $0xc,%esp
  86.                                          # esp + 12
  87.                                          # 释放为了调用 execve() 而压入堆栈的内容
  88. 0x80481c6 :    xorl   %eax,%eax
  89. 0x80481c8 :    jmp    0x80481d0
  90. 0x80481ca :    leal   0x0(%esi),%esi
  91. 0x80481d0 :    leave
  92. 0x80481d1 :    ret

  93. 5. 研究 execve() 函数的执行过程

  94. Linux在寄存器里传递它的参数给系统调用,用软件中断跳到kernel模式(int $0x80)

  95. 0x804b9b0 <__execve>:   pushl  %ebx      # ebx压栈
  96. 0x804b9b1 <__execve+1>: movl   0x10(%esp,1),%edx
  97.                                          # 把 esp + 16 本身赋给edx
  98.                                          # 为什么是16,因为栈顶现在是ebx
  99.                                          # 下面依次是返回地址、name[0]、name、NULL
  100.                                          # edx --> NULL
  101. 0x804b9b5 <__execve+5>: movl   0xc(%esp,1),%ecx
  102.                                          # 把 esp + 12 本身赋给 ecx
  103.                                          # ecx --> name
  104.                                          # 命令的参数数组,包括命令自己
  105. 0x804b9b9 <__execve+9>: movl   0x8(%esp,1),%ebx
  106.                                          # 把 esp + 8 本身赋给 ebx
  107.                                          # ebx --> name[0]
  108.                                          # 命令本身,"/bin/ksh"
  109. 0x804b9bd <__execve+13>:        movl   $0xb,%eax
  110.                                          # 设置eax为0xb,这是syscall表中的索引
  111.                                          # 0xb对应execve
  112. 0x804b9c2 <__execve+18>:        int    $0x80
  113.                                          # 软件中断,转入kernel模式
  114. 0x804b9c4 <__execve+20>:        popl   %ebx
  115.                                          # 恢复ebx
  116. 0x804b9c5 <__execve+21>:        cmpl   $0xfffff001,%eax
  117. 0x804b9ca <__execve+26>:        jae    0x804bcb0 <__syscall_error>
  118.                                          # 判断返回值,报告可能的系统调用错误
  119. 0x804b9d0 <__execve+32>:        ret      # execve() 调用返回
  120.                                          # 该指令会用压在堆栈中的返回地址

  121. 从上面的分析可以看出,完成 execve() 系统调用,我们所要做的不过是这么几项而已:

  122.     a) 在内存中有以NULL结尾的字符串"/bin/ksh"
  123.     b) 在内存中有"/bin/ksh"的地址,其后是一个 unsigned long 型的NULL值
  124.     c) 将0xb拷贝到寄存器EAX中
  125.     d) 将"/bin/ksh"的地址拷贝到寄存器EBX中
  126.     e) 将"/bin/ksh"地址的地址拷贝到寄存器ECX中
  127.     f) 将 NULL 拷贝到寄存器EDX中
  128.     g) 执行中断指令int $0x80

  129. 如果execve()调用失败的话,程序将继续从堆栈中获取指令并执行,而此时堆栈中的数据
  130. 是随机的,通常这个程序会core dump。我们希望如果execve调用失败的话,程序可以正
  131. 常退出,因此我们必须在execve调用后增加一个exit系统调用。
复制代码

这段东东偶看8大明白,请问斑竹要学习那方面的书?有推荐的满?
发表于 2004-5-8 14:24:37 | 显示全部楼层
man execve
man gcc
man gdb
发表于 2004-5-8 15:03:20 | 显示全部楼层
要看懂这样一段东东,首先要懂得linux的系统程序设计。然后是AT&T格式的汇编,熟悉各种系统调用。再熟悉linux的编程环境,自然没有问题。
 楼主| 发表于 2004-5-8 16:11:11 | 显示全部楼层
我在学习c~
汇编以前学过ibm的……看4看的懂点……8过好象一大堆东西放在17就有点迷糊不知道啥结果……
有撒书可以参考捏?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表