欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

第一章:1.2、一个简单的小例子

第一章:1.2、一个简单的小例子

相信各位读者随着上一节学习已经可以顺利找出程序的main函数了,既然如此,那么接下来我们是不是应该做点什么呢?嗯,让我好好想想,我们一起来玩一个小游戏吧,看看我们是否可以让目标程序显示“Hello everybody”,而不是毫无个性的“Hello World”。
      这里我先放出源代码:
int _tmain(int argc, _TCHAR* argv[])
{
    if (argc)
    {
        printf("Hello world!\r\n");
    }
    else
    {
        printf("Hello everybody!\r\n");
    }
  return 0;
}
      各位读者应该都知道程序在执行时会将自己的路径保存到argv字符数组里的,因此argc的值肯定都是始终大于1的,所以程序如果未经处理总是会显示“Hello world!”,现在就让我们给他做一个微型外科手术吧。
      为了更接近实战,所以这次我们要分析Release版的,找到main函数后其内容如下:
00401000  CMP DWORD PTR SS:[ESP+4], 0
00401005  JE SHORT Test_0.00401018
00401007  PUSH Test_0.004020F4                     ; /format = "Hello world!
0040100C  CALL DWORD PTR DS:[<&MSVCR90.printf>]    ; \printf
00401012  ADD ESP, 4
00401015  XOR EAX, EAX
00401017  RETN
00401018  PUSH Test_0.00402104                     ; /format = "Hello everybody!
0040101D  CALL DWORD PTR DS:[<&MSVCR90.printf>]    ; \printf
00401023  ADD ESP, 4
00401026  XOR EAX, EAX
00401028  RETN
      看到这些有些读者应该已经快大叫起来了“这个我知道,改关键跳!”但是请注意,我们现在不是在学爆破,而是在学习逆向,因此
还请各位读者静下心来好好看看这段代码的意思。
      由于ESP是栈指针,ESP的值也就是当前栈的所在位置,而[ESP+4]的意思就是在当前堆栈+4的地方取其内容,那么这句话的意思也就是在当前堆栈+4的地方取其内容,然后与0比较。
      第二句话的意思是检查其比较结果,我们都知道其实cmp指令的作用其实就是对着两个操作数做减法操作,只不过不保存操作结果,仅影响标志位。因此结合起来看可以用C语言描述为如下形式:
    if([ESP+4]!=0)
    { …… }
    else
    { …… }
      但是[ESP+4]我们又怎样理解呢?下面我就带领大家顺便再温习一下栈的结构,先看图:
        ESP = 0012FFE0
      栈地址    栈内容
    ┏━━━━┳━━━━┓
    ┃0012FFE8┃00000000┃▲
    ┣━━━━╋━━━━┫┃
    ┃0012FFEC┃00000000┃┃由
    ┣━━━━╋━━━━┫┃高
  ->┃0012FFF0┃00000000┃┃向
    ┣━━━━╋━━━━┫┃低
    ┃0012FFF4┃00000000┃┃增
    ┣━━━━╋━━━━┫┃长
    ┃0012FFF8┃00000000┃┃
    ┣━━━━╋━━━━┫┃
    ┃0012FFFC┃00000000┃┃
    ┗━━━━┻━━━━┛

    我们应该还记得在进入一个CALL后,其ESP指向的地址为这个CALL的返回地址,如果在调用这个CALL之前压入了一个参数,那么要找到它的方法很定是将当前ESP加上4在取内容,为了更利于各位读者理解这里我为各位举一个比较典型的例子:
…………  …………
00400010  jmp 00400200h
…………  …………
00400100  mov eax,[esp+4] 
00400104  mov [esp-4],eax  ; 将参数2的值传给局部变量1
00400108  mov eax,[esp+8]
0040010C  mov [esp-8],eax  ; 将参数1的值传给局部变量2
00400110  retn             ; 假如我们此时停到这里!EIP = 00400110
…………  …………
00400200  push 11          ; 参数1
00400202  push 22          ; 参数2
00400204  call 00400100
00400209  …………
    它的栈结构大致如下:
        ESP = 0012FFE4
      栈地址    栈内容
    ┏━━━━┳━━━━┓
    ┃0012FFE8┃00000000┃▲
    ┣━━━━╋━━━━┫┃
    ┃0012FFEC┃00000011┃┃由  <- 局部变量2
    ┣━━━━╋━━━━┫┃高
    ┃0012FFF0┃00000022┃┃向  <- 局部变量1
    ┣━━━━╋━━━━┫┃低
  ->┃0012FFF4┃00400209┃┃增  <- 返回地址
    ┣━━━━╋━━━━┫┃长
    ┃0012FFF8┃00000022┃┃    <- 参数2
    ┣━━━━╋━━━━┫┃
    ┃0012FFFC┃00000011┃┃    <- 参数1
    ┗━━━━┻━━━━┛
      本小节就算是又带领大家又大致温习了一下一些基础知识,现在我们回到主题,看看怎样达到我们的目的,我想这应该是很简单的事情了,我目前想出了以下方案:
(1) 将00401005处的JZ改为JMP
(2) 将004020F4处的文本信息改为Hello everybody!
(3) 交给各位完成(提示:与本小节所讲内容相关)【注:谢绝各位大牛们公布答案-_-!】。
      我将在发布下一节教程时公布答案……
答案:
     各位回答的都很不错,不管用的是什么方法,只要解决问题了就是好方法。我在这里就在公布另一个方法,此方法与本节课程联系较大:
第一步、00401007至00401012填充为nop
第二步、在00401007处加上一句push 00401018即可,这样当它执行retn指令时就会返回到00401018处。

【返回到目录】:http://bbs.pediy.com/showthread.php?t=113689

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功