我也来无符号定位驱动入口

本文介绍了一种改进的定位驱动入口方法,通过使用Windbg命令替代手动查找calldwordptr[edi+2c],提高了调试效率。特别强调了如何在IopLoadDriver入口处搜索call[edi+2c]指令,并提供了实际操作步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     老是端着IDA扫射实在不爽,没有真实感,还是不时的debug验证下才好。。。。。

下面是总结的定位驱动入口的方法,方法还是网上的方法,只是不用每次人工找那条邪恶的call dword ptr[edi+2c] 了。。。

 

网上说的调试无符号驱动的方法:在IopLoadDriver+XXX的位置下断点:
xxx随系统不同版本而不同,每次自己拿眼睛找,很累很累,翻了下手册,发现有好命令可用,越来越发现windbg太过强大,只能用时现学了。。。

 

指令格式: # [Pattern] [Address [ L Size ]]
用来搜索汇编指令,windbg提供的这个功能还比较弱,不能直接搜索整条指令,只能这样搜了


在IopLoadDriver入口处开始,大小0x1000的范围内搜索 call [edi+2c]
kd> # "edi?2c" IopLoadDriver L 0x1000
nt!IopLoadDriver+0x684 [e:/wrk/base/ntos/io/iomgr/internal.c @ 4225]:
808ed3e6 ff572c          call    dword ptr [edi+2Ch]
nt!IopCloseFile+0x40 [e:/wrk/base/ntos/io/iomgr/objsup.c @ 156]:
808ef808 f6472c02        test    byte ptr [edi+2Ch],2
nt!IopCloseFile+0x149 [e:/wrk/base/ntos/io/iomgr/objsup.c @ 265]:
808ef911 f6472c02        test    byte ptr [edi+2Ch],2
nt!IopCloseFile+0x1b2 [e:/wrk/base/ntos/io/iomgr/objsup.c @ 313]:

 

还好不多,第一个就是call驱动入口了,接下来就是 bp 808ed3e6; g; s;进入DriverEntry
这是在wrk里哈哈,虽然看见源码的勾引了,但为了日常的没源码环境,我就当啥也没看见。。。

<think>我们正在使用GDB调试程序,并希望通过添加符号表来获取.text段的实际基地址。在GDB中,我们可以通过多种方式获取.text段的基地址,其中一种方法是通过符号表信息。根据引用[4]中的内容,我们可以使用GDB命令`infofiles`或`info target`来查看目标文件的信息,包括各个段的地址。特别地,我们可以查找.text段的信息。另外,引用[4]中还提到,我们可以使用`infoprocmappings`来查看进程的内存映射,这也可以帮助我们找到.text段所在的地址范围。但是,用户的问题是如何通过添加符号表来获取.text段的基地址。这里可能指的是在调试一个没有调试信息的程序时,我们手动添加符号表(例如,通过加载一个单独的调试信息文件),然后获取.text段的基地址。在GDB中,我们可以使用`add-symbol-file`命令来添加符号表。这个命令需要指定符号表文件以及该符号表对应的.text段在内存中的加载地址(基地址)。但是,我们这里的情况可能是反过来:我们想通过添加的符号表来获取基地址。实际上,在添加符号表时,我们需要知道基地址才能正确添加。这似乎是一个先有鸡还是先有蛋的问题。然而,我们可以这样处理:1.如果我们已经知道程序加载的基地址(例如通过`/proc/<pid>/maps`获取),那么我们可以使用这个基地址来添加符号表。2.如果我们不知道基地址,但是我们有程序的未链接的符号表文件(比如一个.o文件或者一个调试信息文件),我们可以先通过其他方法获取基地址(比如查看内存映射),然后再添加符号表。但是,用户希望的是通过添加符号表来获取基地址。这通常不是直接的方法。不过,我们可以尝试以下步骤:假设我们有一个带调试信息的程序,或者一个单独的调试信息文件(比如通过`objcopy`提取的.debug文件),我们可以使用GDB的`file`命令加载这个带调试信息的文件,然后使用`info files`来获取.text段的地址。但是,这个地址是编译时确定的链接地址,而运行时由于ASLR等因素,实际加载地址可能会偏移。因此,我们需要在运行时获取实际加载的基地址。另一种思路:在GDB中,我们可以先附加到进程,然后使用`add-symbol-file`命令,但是`add-symbol-file`要求我们提供符号表加载的地址。如果我们不知道,我们可以尝试不提供地址,然后GDB会尝试使用默认的基地址(即编译时确定的基地址),如果实际加载地址有偏移,那么符号表将无法正确匹配,我们需要调整这个基地址直到符号能够正确解析。但是,我们可以通过以下方法获取实际基地址:步骤1:启动程序并获取其PID。步骤2:通过`/proc/<pid>/maps`查看内存映射,找到主程序或共享库的加载基地址。步骤3:在GDB中,使用`add-symbol-file`命令,指定符号表文件和步骤2中得到的基地址。然后,我们就可以在GDB中使用符号进行调试了。但是,如果我们没有`/proc`文件系统的访问权限,或者我们希望在GDB内部完成所有操作,我们可以这样做:1.在GDB中附加到进程(例如`gdb-p<pid>`)。2.使用GDB命令`infoproc mappings`(或者`infofiles`)来查看内存映射,找到.text段所在的地址范围,起始地址就是基地址(注意,对于动态链接的可执行文件,基地址通常是第一个可执行段的起始地址)。例如,在GDB中:``` (gdb) infofiles```或者```(gdb)info procmappings```在输出中,我们可以找到.text段(通常具有读和执行权限,且是文件映射)的起始地址。那么,如何通过添加符号表来帮助获取基地址?实际上,添加符号表本身并不直接提供基地址,但我们可以利用符号表来验证基地址是否正确。例如,当我们添加符号表时,如果我们提供的基地址正确,那么我们就可以通过符号名访问到正确的地址(比如函数名)。因此,总结一下,获取.text段实际基地址的步骤:方法A(使用GDB内部命令):1.启动GDB并附加到目标进程:`gdb -p <pid>`2.使用`info files`命令,在输出中查找`.text`段的地址(注意,输出中可能以不同的方式描述,但通常会有`.text`段的信息)。3.或者使用`infoproc mappings`,查找具有执行权限的映射,通常第一个映射就是程序的基地址(对于非PIE程序,通常是固定地址,对于PIE程序,每次运行随机)。方法B(使用外部信息):1.通过`/proc/<pid>/maps`文件获取基地址。如果我们想添加符号表,那么我们需要先获取基地址(通过上述方法),然后使用:``` (gdb) add-symbol-file file.sym<base-address>```其中`file.sym`是符号表文件(可能是elf文件或调试信息文件),`<base-address>`就是.text段的基地址。因此,直接回答用户的问题:添加符号表本身并不能直接获取基地址,我们需要先通过其他方法获取基地址,然后才能正确添加符号表。一旦符号表添加成功,我们可以通过符号信息来访问.text段中的函数和变量,但基地址已经是我们之前获取的那个地址。另外,引用[4]中提到,我们可以使用`set`命令来设置一些参数,但这里不适用。下面是一个在GDB中获取基地址的示例:示例步骤:1.启动程序,并获取其PID(假设为1234)。2.启动GDB并附加进程:`gdb-p1234`3.在GDB提示符下输入:(gdb)info files输出可能如下:Symbols from"/path/to/program".Localexec file:`/path/to/program',file typeelf64-x86-64.Entry point:0x5555555550a00x0000555555554318-0x0000555555554334 is.interp0x0000555555554338 -0x0000555555554358 is.note.gnu.property0x0000555555554358-0x000055555555437cis .note.gnu.build-id0x000055555555437c -0x000055555555439c is.note.ABI-tag0x00005555555543a0-0x00005555555543c0 is.gnu.hash0x00005555555543c0 -0x00005555555545a0 is.dynsym...0x00005555555550a0-0x0000555555555180 is.text...这里.text段的起始地址是0x5555555550a0,但注意,对于PIE(位置无关可执行文件),这个地址是运行时随机化的。基地址通常是0x0000555555555000(这个例子中,程序的基地址实际上是0x0000555555554000,因为前面的段从0x0000555555554318开始,但通常基地址是第一个LOAD段的虚拟地址,而第一个LOAD段通常包含程序头和.init等段,然后第二个LOAD段包含.text等)。更简单的方法是看第一个LOAD段的虚拟地址,可以使用`readelf -l`查看程序头,在运行时,第一个LOAD段的虚拟地址就是基地址。在GDB中,我们可以使用`infoproc mappings`来查看更清晰的内存映射:(gdb) infoproc mappings输出类似:StartAddrEnd AddrSizeOffsetobjfile0x5555555540000x5555555550000x10000x0/path/to/program0x5555555550000x5555555560000x10000x1000/path/to/program...通常,第一个可执行段(权限为r-xp)就是.text段所在的段,其起始地址(0x555555555000)就是.text段的基地址(注意,这里基地址是0x555555554000,而.text段在0x555555555000,所以.text段的基地址是0x555555555000,但整个程序的基地址是0x555555554000)。所以,我们通常将整个程序的基地址称为基地址(即第一个LOAD段的虚拟地址),而.text段的基地址则是包含.text段的那个LOAD段的虚拟地址。在非PIE程序中,程序的基地址和.text段的基地址通常是固定的(例如0x400000)。因此,在回答中,我们需要明确用户所说的.text段的实际基地址是指整个程序的基地址还是.text段在内存中的起始地址。通常,我们关心的是整个程序的基地址,因为它是所有段偏移的参考。结论:在GDB中,我们可以通过`infofiles`或`info procmappings`来获取.text段的实际基地址(即运行时内存中的起始地址),而无需通过添加符号表。添加符号表需要基地址作为参数,而不是提供基地址。如果用户已经有一个符号表文件,并且想通过这个文件来获取基地址,那么实际上这个文件中的地址是编译时的链接地址。在运行时,如果程序是PIE,那么实际地址会有一个偏移(一个随机值)。我们可以通过比较运行时的某个地址(比如入口点)和符号表中的入口点地址,计算出偏移量,然后根据这个偏移量调整符号表中的所有地址。但是,这个过程比较复杂,通常我们使用GDB的自动匹配功能(即通过`add-symbol-file`指定基地址)来完成。因此,建议用户先通过GDB的`infoproc mappings`获取基地址,然后再添加符号表。下面是一个完整的示例:假设我们有一个程序,它已经运行,PID为1234,我们还有一个符号表文件`program.debug`(通过`objcopy --only-keep-debug programprogram.debug`生成)。步骤:1.启动GDB并附加到进程:`gdb -p1234`2.在GDB中,获取基地址:(gdb) infoproc mappings输出中,找到主程序文件映射的具有执行权限的段,例如:0x5555555540000x5555555550000x10000x0/path/to/program0x5555555550000x5555555560000x10000x1000/path/to/program[这里.text段通常位于这个段]注意,第一个可执行段(权限为r-xp)的起始地址是0x555555555000,这就是.text段所在的基地址(注意,整个程序的基地址是0x555555554000,但是.text段从0x555555555000开始)。3.添加符号表,指定符号表文件以及.text段的基地址(0x555555555000):(gdb)add-symbol-fileprogram.debug0x555555555000这样,符号表就加载到了正确的地址。注意:在非PIE程序中,程序的基地址是固定的(例如0x400000),而.text段可能从0x401000开始。所以我们需要根据实际情况提供基地址。如果用户不知道应该提供哪个地址,可以查看符号表文件中的.text段的地址(使用`readelf-S program.debug`),然后计算运行时和编译时的偏移量,然后调整。但是,通常我们提供的是运行时的.text段的起始地址。因此,回答用户的问题:在GDB中,通过添加符号表来获取.text段的实际基地址是不可行的。我们需要先获取基地址,然后才能正确添加符号表。获取基地址的方法如上所述。相关问题:1.如何通过GDB获取动态链接库的基地址?2.在存在ASLR的情况下,如何计算运行时地址与链接时地址的偏移量?3.如何为分离的调试信息文件添加符号表?4.在GDB中,如何验证添加的符号表是否正确?5.如何为正在运行的进程添加多个共享库的符号表?</think>### 通过 GDB 添加符号表获取 .text 段基地址 在 GDB 调试中,可以通过添加符号表并结合特定命令获取程序运行时 .text 段的实际基地址。以下是详细步骤: #### 方法 1:使用 `info files` 命令(推荐) 1. **添加符号表** 启动 GDB 并加载可执行文件: ```bash gdb ./your_program ``` 或附加到运行中的进程: ```bash gdb -p <PID> ``` 2. **获取 .text 段基地址** 在 GDB 中执行: ```gdb (gdb) info files ``` 查找输出中 `.text` 段的信息: ``` Symbols from "your_program". Local exec file: `/path/to/your_program', file type elf64-x86-64. Entry point: 0x5555555551a0 0x00005555555551a0 - 0x00005555555556a0 is .text # 基地址为 0x5555555551a0 ``` **关键字段**:`.text` 前的地址即实际基地址[^4]。 #### 方法 2:使用 `readelf` 预解析 1. **静态获取链接地址** ```bash readelf -S ./your_program | grep .text ``` 输出示例: ``` [13] .text PROGBITS 00000000000011a0 00011a0 00001d45 ``` 地址 `0x11a0` 是链接时的基地址。 2. **结合运行时 ASLR 偏移** 在 GDB 中获取实际偏移: ```gdb (gdb) info proc mappings ``` 查找第一条 `r-xp` 映射: ``` 0x555555554000 0x555555555000 0x1000 0x0 /path/to/your_program ``` 实际基地址 = 链接地址 + 偏移量 = `0x11a0 + 0x555555554000 = 0x5555555551a0`[^4]。 #### 方法 3:通过入口点计算 1. **获取入口地址** ```gdb (gdb) info files | grep "Entry point" Entry point: 0x5555555551a0 ``` 2. **计算 .text 偏移** 使用 `readelf` 获取 .text 段相对于入口点的偏移: ```bash readelf -s ./your_program | grep _start ``` 输出: ``` 65: 00000000000011a0 43 FUNC GLOBAL DEFAULT 13 _start ``` 实际基地址 = 入口地址 - `_start` 偏移 = `0x5555555551a0 - 0x11a0 = 0x555555554000`[^4]。 #### 添加外部符号表 当调试剥离符号的程序时: ```gdb (gdb) add-symbol-file external_debug_info 0x5555555551a0 -s .text 0x5555555551a0 ``` 其中 `external_debug_info` 是分离的调试文件,`0x5555555551a0` 是通过上述方法获取的 .text 基地址[^4]。 #### 验证方法 ```gdb (gdb) p/x &main # 获取 main 函数地址 $1 = 0x5555555551a0 (gdb) info symbol 0x5555555551a0 main in section .text # 确认位于 .text 段 ``` ### 关键点说明 1. **ASLR 影响** 每次运行的基地址可能不同,需动态获取[^4]。 2. **PIE 位置无关可执行文件** 基地址通常是随机化的,需通过 `/proc/[pid]/maps` 或 `info proc mappings` 获取[^4]。 3. **段偏移计算** `.text` 的实际地址 = 程序加载基地址 + ELF 文件中的 .text 偏移量。 ### 相关问题 1. **如何获取动态链接库(.so)的 .text 段基地址?** 2. **当程序启用 ASLR 时,如何准确定位 .text 段?** 3. **如何为剥离符号的可执行文件生成分离的调试信息?** 4. **在 GDB 中如何直接获取当前程序的完整内存映射布局?** 5. **如何通过程序计数器(PC)寄存器验证 .text 段位置?** [^1]: GDB 的 `list` 命令可用于查看源代码和行号信息 [^2]: ELF 文件中的字符串表结构及作用 [^3]: Linux 字符设备驱动注册相关函数 [^4]: GDB 调试技巧合集,包括符号加载、内存映射查看等高级功能
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值