首页
论坛
课程
招聘
[原创]利用windbg脚本调试简单实例
2011-11-15 22:13 22351

[原创]利用windbg脚本调试简单实例

2011-11-15 22:13
22351
之前想写一篇用windbg脚本调试的东西,但是一直比较懒,懒得动手,懒得想例子,把时间都放在了游戏上面,所以想法虽好一直没有实施...
    这次写一个非常简单的利用windbg脚本进行动态调试的小文,博君一笑.
    // Windbgscript.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <iostream>
using namespace std;


int ret100()
{
  [B]int x = 2;[/B]  //2-3
  x*=33;
  ++x;

  return x;
}

int add(int x, int y)
{
  [B]x = 0;[/B] //多余的
  return x+y;

}


int _tmain(int argc, _TCHAR* argv[])
{

  int x = 100;

  int y = add( x, ret100());

  cout << y;

  getchar();
  return 0;
}

    上面代码都非常简单,ret100里面做了一个非常简单的操作,我希望它的返回值是100,但现在的返回值是67, 当然改法太多了,我这里假设是初始化时 x 应该初始化为3. 
    同样add里面也有问题,就是对于参数x赋值0,认为它是一条多余的操作, 因为我们的目的是返回x+y的结果.
现在执行结果是:
  
 

如何利用windbg去动态的修改并且不需要我们始终去手动交互是我们的主要目的, 首先肯定是要了解这两个函数的内部实现.
uf伺候:

0:001> uf windbgscript!ret100
   11 00401000 55              push    ebp
   11 00401001 8bec            mov     ebp,esp
   11 00401003 51              push    ecx
 [B]  12 00401004 c745fc02000000  mov     dword ptr [ebp-4],2
   [U]13 0040100b 8b45fc          mov     eax,dword ptr [ebp-4][/U][/B]
   13 0040100e 6bc021          imul    eax,eax,21h
   13 00401011 8945fc          mov     dword ptr [ebp-4],eax
   14 00401014 8b4dfc          mov     ecx,dword ptr [ebp-4]
   14 00401017 83c101          add     ecx,1
   14 0040101a 894dfc          mov     dword ptr [ebp-4],ecx
   16 0040101d 8b45fc          mov     eax,dword ptr [ebp-4]
   17 00401020 8be5            mov     esp,ebp
   17 00401022 5d              pop     ebp
   17 00401023 c3              ret

 mov     dword ptr [ebp-4],2
对应的就是 x=2;的指令, 我们的目的是将x赋值3, 这里改法很多,比如将ebp-4处赋值3并跳过该指令...
这里选择最简单的,让该指令执行,再执行下一条指令前修改x的值.
bp windbgscript!ret100 + 0xb " $$ 0xb代表从函数ret100开始处到当前断点位置的偏移
  ed (ebp-4) 3; $$当代码执行到此处时,ebp-4即代表x的内存地址, ed命令为在制定地指处 赋值
 gc;  $$gc命令表示脚本执行后,程序会继续执行
"


0:001> uf windbgscript!add
   20 00401030 55              push    ebp
   20 00401031 8bec            mov     ebp,esp
   [B]21 00401033 c7450800000000  mov     dword ptr [ebp+8],0[/B]
   22 0040103a 8b4508          mov     eax,dword ptr [ebp+8]
   22 0040103d 03450c          add     eax,dword ptr [ebp+0Ch]
   24 00401040 5d              pop     ebp
   24 00401041 c3              ret

mov     dword ptr [ebp+8],0
即为那条多余的指令x=0; 我们的目的是让cpu忽略这条指令, 做法是在这条指令被执行前修改eip的值,始之跳转到下一条指令处继续执行
bp windbgscript!add + 0x03 "
 r @eip = @eip+0xa; $$ @符号会让脚本解释程序认为后面跟随的名称代表为寄存器, 节省查找时间,提高效率
 gc;
"

加载windbg脚本后程序的执行结果:
 

实在是找不出好的例子来,所以就想出了这么个下三滥的例子,莫笑。。。
   实际中这么简单的程序谁也不会用windbg调试的,编写脚本的时间可能远远比重新编译,部署,调试所消耗的时间更长。
   个人认为这种脚本还是比较适合用在重现问题比较困难, 尤其是一种场景, 一个进程开始的时候没有任何问题,但是跑一段时间(比如2-3个小时)开始不断重复出现一连串的错误(非崩溃),这种场景用windbg脚本还是非常合适的。
   windbg脚本里的命令非常丰富,基本平时能用到的功能都有了,感兴趣翻翻帮助文档学学还是很不错的。

  谢谢

【看雪培训】《Adroid高级研修班》2022年夏季班招生中!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (18)
雪    币: 5526
活跃值: 活跃值 (823)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
email123 活跃值 2011-11-15 22:49
2
0
不错,又学了一招,希望楼主多出这样简单易懂的文章!谢谢了
雪    币: 384
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
leeone 活跃值 2011-11-15 23:36
3
0
这种太简单了,lz整下字符串的匹配吧,多字节编码和unicode编码,大小写敏感,子串匹配,自由组合。
当然自己写插件就简单了。
雪    币: 168
活跃值: 活跃值 (25)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
levizhou 活跃值 1 2011-11-16 09:22
4
0
对,这个确实非常简单

因为我觉得写的简单点儿比较容易被接受, 太复杂了就不是教程贴了
雪    币: 482
活跃值: 活跃值 (939)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
sudami 活跃值 25 2011-11-16 11:59
5
0
厉害啊。来点实战的吧
雪    币: 1570
活跃值: 活跃值 (10)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
柳州小林 活跃值 2 2011-11-22 10:00
6
0
不错不错,以后修改多个跳转就方便了
雪    币: 0
活跃值: 活跃值 (24)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
tihty 活跃值 2 2011-11-24 15:35
7
0
看看。。:)
雪    币: 107
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tydef 活跃值 2011-11-24 16:32
8
0
THX
来点内核 脚本调试范例如何?
雪    币: 168
活跃值: 活跃值 (25)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
levizhou 活跃值 1 2011-11-24 17:30
9
0
实在不好意思, 对内核调试的东西一无所知啊
雪    币: 181
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
殁十一 活跃值 2011-11-26 00:15
10
0
  看看
雪    币: 97
活跃值: 活跃值 (65)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
hash 活跃值 2011-11-28 19:11
11
0
int add(int x, int y)
{
  x = 0; //多余的
  return x+y;

}
脑子里以为 x= 0 这条指令会在栈中开辟空间,怎么是从参数传了。因为是函数内部局部变量,我还以为是 mov DWORD PTR [ebp-4],0 呢。求指点
雪    币: 168
活跃值: 活跃值 (25)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
levizhou 活跃值 1 2011-11-29 19:41
12
0
[QUOTE=hash;1024496]int add(int x, int y)
{
  x = 0; //多余的
  return x+y;

}
脑子里以为 x= 0 这条指令会在栈中开辟空间,怎么是从参数传了。因为是函数内部局部变量,我还以为是 mov DWORD PTR [ebp-4],0 呢。求指点[/QUOTE]

首先x会在栈中有位置 -- 参数位置

其次,栈是逆向生长的,所以定位参数需要 ebp+?

最后,默认压栈次序为倒序, 再加上eip会占一个位置,然后 y, 最后 x 所以x 在栈上的位置: ebp+8
雪    币: 222
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Dvsz 活跃值 2012-2-4 19:47
13
0
谢谢楼主分享!
雪    币: 1644
活跃值: 活跃值 (53)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yodamaster 活跃值 2012-2-8 10:53
14
0
感谢分享。。。
雪    币: 100
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lactor 活跃值 2012-2-13 17:26
15
0
顶,学习了。
雪    币: 15
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cosmoer 活跃值 2012-5-23 15:30
16
0
代码:
bp windbgscript!add + 0x03 "
r @eip = @eip+0xa; $$ @符号会让脚本解释程序认为后面跟随的名称代表为寄存器, 节省查找时间,提高效率
gc;
"
请问,为什么是+0xa,而不是+0x7?
雪    币: 168
活跃值: 活跃值 (25)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
levizhou 活跃值 1 2012-5-24 08:57
17
0
应该是0x7, 可能我当时打错字了;我那里有存根回去看下修正
多谢细心指出
雪    币: 168
活跃值: 活跃值 (25)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
levizhou 活跃值 1 2012-5-24 09:26
18
0
windbgscript!main [e:\workspace\windbgscript\windbgscript.cpp @ 28]:
   28 00401050 55              push    ebp
   28 00401051 8bec            mov     ebp,esp
   28 00401053 83ec0c          sub     esp,0Ch
   30 00401056 c745f864000000  mov     dword ptr [ebp-8],64h
   32 0040105d e89effffff      call    windbgscript!ret100 (00401000)
   32 00401062 50              push    eax
   32 00401063 8b45f8          mov     eax,dword ptr [ebp-8]
   32 00401066 50              push    eax
   32 00401067 e8c4ffffff      call    windbgscript!add (00401030)
   32 0040106c 83c408          add     esp,8
   32 0040106f 8945fc          mov     dword ptr [ebp-4],eax
   34 00401072 8b4dfc          mov     ecx,dword ptr [ebp-4]
   34 00401075 51              push    ecx
   34 00401076 b980614100      mov     ecx,offset windbgscript!std::cout (00416180)
   34 0040107b e850000000      call    windbgscript!std::basic_ostream<char,std::char_traits<char> >::operator<< (004010d0)
   36 00401080 8b159c534100    mov     edx,dword ptr [windbgscript!_iob+0x4 (0041539c)]
   36 00401086 83ea01          sub     edx,1
   36 00401089 89159c534100    mov     dword ptr [windbgscript!_iob+0x4 (0041539c)],edx
   36 0040108f 7822            js      windbgscript!main+0x63 (004010b3)

两处巧合导致错误的脚本得出了和预期一样的结果
1. 第二条指令恰好3个字节 -- +0xa 没问题
2. 下一条指令给eax赋值100, 而此时eax就是100 -- main里赋的值
雪    币: 78
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
ronging 活跃值 2012-5-25 14:31
19
0
游客
登录 | 注册 方可回帖
返回