windbg内存断点学习总结

591 篇文章 6 订阅 ¥99.90 ¥99.00
281 篇文章 6 订阅
105 篇文章 2 订阅

Windbg中使用查找内存并设置访问断点

http://www.cnblogs.com/SkyMouse/archive/2012/06/06/2538745.html


在windbg中通过s 命令在内存中查找字符串或者关键字节码信息


0:005> s -u 00c00000 L1000000 "你好 20:15 2012/6/620:15 2012/6/6"
 
01960d28  4f60 597d 0020 0032 0030 003a 0031 0035  `O}Y .2.0.:.1.5.
查看内存01960d28 


01960d28 00 00 00 00 00 00 00 00 30 00 3a 00 31 00 35 00 20 00  ........0.:.1.5. .
01960d3a 32 00 30 00 31 00 32 00 2f 00 36 00 2f 00 36 00 32 00  2.0.1.2./.6./.6.2.
01960d4c 30 00 3a 00 31 00 35 00 20 00 32 00 30 00 31 00 32 00  0.:.1.5. .2.0.1.2.
 
01960d5e 2f 00 36 00 2f 00 36 00 00 00 00 00 00 00 00 00 00 00  /.6./.6...........
找到内容之后通过ba设置访问断点在任何函数访问该内存时将会中断


0:005> ba r4 01960d28  
 
0:005> bl
 0 du             0001 (0001) (@@masm(`ItemOperation.cpp:60+`))
 1 e 01960d28 r 4 0001 (0001)  0:**** 
 2 e 771c3540     0001 (0001)  0:**** ntdll!DbgBreakPoint
如此在程序访问该地址时将会中断到调试器


0:005> g
Breakpoint 1 hit
eax=019607d0 ebx=00000023 ecx=00000003 edx=0000002c esi=019607d0 edi=01960cd0
eip=76d29c9c esp=000fefa4 ebp=000fefa8 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
msvcrt!_VEC_memcpy+0x125:
76d29c9c 660f7f4760      movdqa  xmmword ptr [edi+60h],xmm0 ds:0023:01960d30=003100300032002000350031003a0030
当然也可以根据自身需要查找相应的其他内容来实现设置相应的访问断点
========

谁动了我的指针?--记一次WINDBG内存断点的使用

http://www.cppblog.com/ay19880703/archive/2012/01/03/163486.html
 
写驱动的时候有个地方老是蓝屏,看了dump发现数据被非法篡改了.
数据初始化如下
 
if(record_set_ptr != NULL )
{
    record_set_ptr->look_aside_pool_ptr = g_user_control_context.look_aside_pools[type] ;
    record_set_ptr->type = type ;
    record_set_ptr->buffer_size = notify_count * unit_size_of ;
    record_set_ptr->units_count = notify_count ;
    record_set_ptr->complete_count = 0 ;
}
然后在调用ExFreeToNPagedLookasideList传入record_set_ptr->look_aside_pool_ptr 的时候挂了,发现record_set_ptr->look_aside_pool_ptr已经被改了.
 
为了跟踪数据在哪里被修改了,先在数据初始化的地方下断,然后记下record_set_ptr->look_aside_pool_ptr 的地址:0x85c16018
对这个内存下个断点
1: kd> ba w4 85c16018
w表示在写入时断下,4表示监控范围,单位是字节 
整个命令的意思就是让调试器在系统写入内存85c16018-85c1601b这个地址范围的时候中断
OK,命令下完,F5一下就立马断下来了
1: kd> g
Breakpoint 3 hit
nt!memcpy+0x33:
8053b583 f3a5            rep movs dword ptr es:[edi],dword ptr [esi]


此时edi的值: 0x85c16018
 
最后看一下函数堆栈,发现是字符串拷贝越界覆盖了后面的数据.... 
后面又想到,出错时record_set_ptr->look_aside_pool_ptr 的值是0x005c0065
这么明显的字符串特征竟然没意识到....一看出错值就应该知道是字符串覆盖造成的.....
posted on 2012-01-03 15:07 __ay 阅读(3020) 评论(3)  编辑 收藏 引用 所属分类: Debugging


Feedback
# re: 谁动了我的指针?--记一次windbg内存断点的使用 2012-01-05 09:33 zuhd
和楼主分享一下: 
一般遇到这种需要下内存断点的调试,我可能会先检查代码,应该会有90%的概率是越界造成的,确定该内存是在堆还是栈,然后排查该变量上下的两个变量,基本都能找到,呵呵。请问楼主是UESTC的吗?  回复  更多评论   
# re: 谁动了我的指针?--记一次windbg内存断点的使用 2012-01-05 13:30 __ay
呵呵 你也是UESTC的?不过我已经毕业了 
当然如果越界的时候能直接引发崩溃,那么看代码直接就能解决问题
但是在越界读写不引发crash,直到引用被覆盖的数据的时候才崩溃,如果这个时候代码中很难定位到被覆盖数据是什么时候写的,那应该用内存断点会比较好了@zuhd
========

windbg memory breakpoint 内存断点

http://blog.csdn.net/kelsel/article/details/50503918


ba (Break on Access)  
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
kd> ba i4 3f8  


Kernel-Mode
ba[ID] Access Size [Options] [Address [Passes]] ["CommandString"]


Access
Specifies the type of access that satisfies the breakpoint. This parameter can be one of the following values.
Option Action
e (execute)
Breaks into the debugger when the CPU retrieves an instruction from the specified address.
r(read/write)
Breaks into the debugger when the CPU reads or writes at the specified address.
w (write)
Breaks into the debugger when the CPU writes at the specified address.
i (i/o)
(Microsoft Windows XP and later versions, kernel mode only, x86-based systems only) Breaks into the debugger when the I/O port at the specified Address is accessed.
 
 Size
Specifies the size of the location, in bytes, to monitor for access. On an x86-based processor, this parameter can be 1, 2, or 4. However, if Access equals e, Sizemust be 1.
On an x64-based processor, this parameter can be 1, 2, 4, or 8. However, if Access equals e, Size must be 1.


https://msdn.microsoft.com/en-us/library/windows/hardware/ff538165(v=vs.85).aspx
========

windbg --内存数据断点 

http://blog.sina.com.cn/s/blog_4e0987310101a975.html


ba (Break on Access)
The ba command sets a data breakpoint. This breakpoint is triggered when the specified memory is accessed.
Syntax
User-Mode
[~Thread] ba[ID] Access Size [Options] [Address [Passes]] ["CommandString"] 
Kernel-Mode
ba[ID] Access Size [Options] [Address [Passes]] ["CommandString"] 
Parameters
Thread
Specifies the thread that the breakpoint applies to. For more information about syntax, see Thread Syntax. You can specify threads only in user mode.
ID
Specifies an optional number that identifies the breakpoint. If you do not specify ID, the first available breakpoint number is used. You cannot add space between ba and the ID number. Each processor supports only a limited number of data breakpoints. But there is no restriction on the value of the ID number. If you enclose ID in square brackets ([]), ID can include any expression. For more information about the syntax, see Numerical Expression Syntax.
Access
Specifies the type of access that satisfies the breakpoint. This parameter can be one of the following values.
Option Action
e (execute) Breaks into the debugger when the CPU retrieves an instruction from the specified address.
r (read/write) Breaks into the debugger when the CPU reads or writes at the specified address.
w (write) Breaks into the debugger when the CPU writes at the specified address.
i (i/o) (Microsoft Windows XP and later versions, kernel mode only, x86-based systems only) Breaks into the debugger when the I/O port at the specified Address is accessed.
You cannot add space between Access and Size.
Note  On Windows Server 2003 with Service Pack 1 (SP1), on an Itanium-based computer that uses WOW64 to emulate x86, data breakpoints do not work with the execute option but they do work with the read and write options.
Size
Specifies the size of the location, in bytes, to monitor for access. On an x86-based processor, this parameter can be 1, 2, or 4. However, if Access equals e, Size must be 1.
On an x64-based processor, this parameter can be 1, 2, 4, or 8. However, if Access equals e, Size must be 1.
On an Itanium-based processor, this parameter can be any power of 2, from 1 to 0x80000000.
You cannot add space between Access and Size.
Options
Specifies breakpoint options. You can use any number of the following options, except as indicated:
/1
Creates a "one-shot" breakpoint. After this breakpoint is triggered, the breakpoint is permanently removed from the breakpoint list.
/f PredNum
(Itanium only, user mode only) Specifies a predicate number. The breakpoint is predicated with the corresponding predicate register (for example, bp /f 4 address sets a breakpoint that is predicated with the p4 predicate register). For more information about predicate registers, see Itanium Architecture.
/p EProcess
(Kernel mode only) Specifies a process that is associated with this breakpoint. EProcess should be the actual address of the EPROCESS structure, not the PID. The breakpoint is triggered only if it is encountered in the context of this process.
/t EThread
(Kernel mode only) Specifies a thread that is associated with this breakpoint. EThread should be the actual address of the ETHREAD structure, not the thread ID. The breakpoint is triggered only if it is encountered in the context of this thread. If you use /p EProcess and /t EThread , you can enter them in either order.
/c MaxCallStackDepth
Causes the breakpoint to be active only when the call stack depth is less than MaxCallStackDepth. You cannot combine this option together with /C.
/C MinCallStackDepth
Causes the breakpoint to be active only when the call stack depth is larger than MinCallStackDepth. You cannot combine this option together with /c.
Address
Specifies any valid address. If the application accesses memory at this address, the debugger stops execution and displays the current values of all registers and flags. This address must be an offset and suitably aligned to match the Size parameter. (For example, if Size is 4, Address must be a multiple of 4.) If you omit Address, the current instruction pointer is used. For more information about the syntax, see Address and Address Range Syntax.
Passes
Specifies the number of times the breakpoint is passed by until it activates. This number can be any 16-bit value. The number of times the program counter passes through this point without breaking is one less than the value of this number. Therefore, omitting this number is the same as setting it equal to 1. Note also that this number counts only the times that the application executes past this point. Stepping or tracing past this point does not count. After the full count is reached, you can reset this number only by clearing and resetting the breakpoint.
CommandString
Specifies a list of commands to execute every time that the breakpoint is encountered the specified number of times. These commands are executed only if the breakpoint is hit after you issue a g (Go) command, instead of after a t (Trace) or p (Step) command. Debugger commands in CommandString can include parameters.
You must enclose this command string in quotation marks, and you should separate multiple commands by semicolons. You can use standard C control characters (such as \n and \"). Semicolons that are contained in second-level quotation marks (\") are intepreted as part of the embedded quoted string.
This parameter is optional
Environment
Modes User mode, kernel mode
Targets Live debugging only
Platforms All
Comments
The debugger uses the ID number to refer to the breakpoint in later bc (Breakpoint Clear), bd (Breakpoint Disable), and be (Breakpoint Enable), commands. Use the bl (Breakpoint List) command to see the ID numbers that are associated with all currently set breakpoints.
The ba command provides the same functionality that the debug registers provide. You can break execution when the particular memory location is read from, written to, or executed.
The breakpoint is satisfied only when the access occurs at the given address and for the specified number of bytes. If the memory that is accessed overlaps the specified area to monitor, the breakpoint is not satisfied.
Although the size is required for all breakpoint types, an execute breakpoint is satisfied only if the address is the first byte in the instruction.
When you debug a multiprocessor system in kernel mode, breakpoints that you set by using bp (Set Breakpoint) or ba apply to all processors. For example, if the current processor is 3 and you type ba e1 MemoryAddress to put a breakpoint at MemoryAddress, any processor (not only processor 3) that executes at that address causes a breakpoint trap.
You cannot set the initial breakpoint in a user-mode process by using the ba command.
You cannot create multiple breakpoints at the same address that differ only in their CommandString values. However, you can create multiple breakpoints at the same address that have different restrictions (for example, different values of the /p, /t, /c, and /C options).
When you debug in kernel mode, the target computer distinguishes between user-mode and kernel-mode data breakpoints. A user-mode data breakpoint cannot affect kernel execution or memory access. A kernel-mode data breakpoint might affect user-mode execution or memory access, depending on whether the user-mode code is using the debug register state and whether there is a user-mode debugger that is attached.
To apply the current process' existing data breakpoints to a different register context, use the .apply_dbp (Apply Data Breakpoint to Context) command.
The following examples show the ba command. The following command sets a breakpoint for read access on 4 bytes of the variable myVar.
0:000> ba r4 myVar
The following command adds a breakpoint on all serial ports with addresses from 0x3F8 through 0x3FB. This breakpoint is triggered if anything is read or written to these ports.
kd> ba i4 3f8
========

两次内存断点法寻找OEP

http://www.programlife.net/twice-breakpoint-find-oep.html


逆向过程中通过会遇到脱壳的过程,而脱壳的方式有有多重,如果手工脱壳,需要找到OEP。
所谓“两次内存断点法寻找OEP”,按照《加密与解密*第三版》上的解释来说,就是这样的。
一般的外壳会依次对.text、.rdata、.data、.rsrc区块进行解压(解密)处理,所以,可以先在.rdata、.data等区块下内存访问断点,中断后,此时代码已解压,接着再对代码段(.text)下内存访问断点,即可到达OEP。


我个人的理解是所有节区都解压完毕之后,然后程序的执行流会转移到OEP,这个时候自然回去访问相应的代码,所以就会断下;实际操作的时候还需要多一个跟踪步骤。


这里以一个UPX加壳的程序为例:
首先OD加载程序,Alt + M打开内存映射视图,找到主模块的数据段或者资源段F2下访问中断,如图。
对数据段或者资源段下F2访问中断


然后F9运行程序,会自动断下,再次Alt + M打开内存映射视图,找到代码段F2下访问中断,如图。
对代码段下F2访问中断


之后F9运行,会再次断下。这个时候仍然Alt + M打开内存映射视图,观察一下主模块的区块。




0040BA75    8D8430 58B00000 LEA EAX,DWORD PTR DS:[EAX+ESI+B058]
0040BA7C    01F3            ADD EBX,ESI
0040BA7E    50              PUSH EAX
0040BA7F    83C7 08         ADD EDI,8
0040BA82    FF96 94B00000   CALL DWORD PTR DS:[ESI+B094]             ; KERNEL32.LoadLibraryA
0040BA88    95              XCHG EAX,EBP
0040BA89    8A07            MOV AL,BYTE PTR DS:[EDI]
0040BA8B    47              INC EDI
0040BA8C    08C0            OR AL,AL
0040BA8E  ^ 74 DC           JE SHORT 0040BA6C
0040BA90    89F9            MOV ECX,EDI
Memory map, 项目 18
 地址=00401000
 大小=00008000 (32768.)
 属主=UpxDemo  00400000
 区段=UPX0
 类型=映像 01001002
 访问=R
 初始访问=RWE
Memory map, 项目 19
 地址=00409000
 大小=00003000 (12288.)
 属主=UpxDemo  00400000
 区段=UPX1
 包含=SFX,代码
 类型=映像 01001002
 访问=R
 初始访问=RWE
看到UPX0和UPX1到底哪一个是真实的代码块呢?需要试一下。对于UPX0,VA的范围是00401000~00409000,对于UPX1,VA的范围是00409000~0040C000。可以在OD的命令行中执行tc eip<00409000,按Enter执行,发现来到了OEP了。(同样可以测试tc eip<0040C000,但得到的不是OEP)。


00401120    55              PUSH EBP
00401121    8BEC            MOV EBP,ESP
00401123    6A FF           PUSH -1
00401125    68 B8504000     PUSH 004050B8
0040112A    68 EC1D4000     PUSH 00401DEC
0040112F    64:A1 00000000  MOV EAX,DWORD PTR FS:[0]
00401135    50              PUSH EAX
00401136    64:8925 0000000>MOV DWORD PTR FS:[0],ESP
0040113D    83EC 58         SUB ESP,58
00401140    53              PUSH EBX
00401141    56              PUSH ESI
00401142    57              PUSH EDI
00401143    8965 E8         MOV DWORD PTR SS:[EBP-18],ESP
00401146    FF15 28504000   CALL DWORD PTR DS:[405028]               ; KERNEL32.GetVersion
0040114C    33D2            XOR EDX,EDX
0040114E    8AD4            MOV DL,AH
00401150    8915 14854000   MOV DWORD PTR DS:[408514],EDX
00401156    8BC8            MOV ECX,EAX
00401158    81E1 FF000000   AND ECX,0FF
0040115E    890D 10854000   MOV DWORD PTR DS:[408510],ECX
00401164    C1E1 08         SHL ECX,8
附:
TC (Trace in till condition)跟踪进入直到条件
更多参考:http://www.pediy.com/bbshtml/BBS5/pediy50401.htm
========
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Windbg(Windows Debugger)是微软官方提供的一款强大的调试工具,主要用于分析和调试Windows系统下的应用程序。设置断点是调试过程中的重要步骤,它允许你在程序执行到特定行或代码块时暂停,以便查看和修改变量值、检查调用堆栈等。 以下是设置断点的基本步骤: 1. **打开Windbg**:首先,你需要打开Windbg,可以通过“开始”菜单搜索或直接运行`cdb.exe`(命令行版)或`windbg.exe`(图形界面版)。 2. **加载目标模块**:如果你知道要调试的应用程序的进程ID(PID)或进程名,使用`!process`命令加载它。例如:`.reload /f <进程名>` 或 `~pid <进程ID>`。 3. **找到源代码位置**:在加载了目标模块后,使用`lm`(list modules)命令查看模块信息,然后找到你想要设置断点的源代码行号,通常文件路径会出现在模块信息中。 4. **设置断点**:使用`bp`命令加上模块路径和行号,例如:`bp <模块路径>\function_name + line_number`。你也可以使用符号文件(.pdb)的相对路径来设置断点,如:`bp !function_name`。 5. **断点选项**:如果需要,你可以添加条件、步进等选项,例如设置只在满足某个条件时触发断点,用`b`命令后跟条件表达式,如 `b function_name(line_number) condition`。 6. **启动调试**:最后,启动你要调试的进程,Windbg会在设置的断点处停止程序执行。 相关问题: 1. Windbg除了断点还有哪些调试功能? 2. 如何在Windbg中单步执行代码? 3. 如何查看断点列表和管理已设置的断点

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值