调试运行在Wow64子系统下的程序----x64版windbg调试win32程序

article/2025/9/26 8:35:26

    大家有没有遇到过这种情况:程序崩溃了,windbg分析线程堆栈时,输出了一堆乱七八糟的调用栈。更烦心的是,这堆调用栈中根本找不到跟自己程序相关的信息。来看一个类似的场景:运行C:\Windows\SysWOW64\calc.exe (win32版的calc.exe),windbg(x64 bit)附加到calc.exe:

0:003> ~*kb0  Id: 2718.1c98 Suspend: 1 Teb: 00000000`7efdb000 Unfrozen# RetAddr           : Args to Child                                                           : Call Site
00 00000000`741fae90 : 00000000`00000000 00000000`7420342a 00000000`00000000 00000000`0005138e : wow64win!ZwUserGetMessage+0xa
01 00000000`7424d18f : 00000000`0017ef6c 00000000`7efdb000 00000000`7efdd000 00000000`741faef4 : wow64win!whNtUserGetMessage+0x30
02 00000000`741d2776 : 00000000`74b378d7 00000000`74240023 00000000`00200246 00000000`0017ef64 : wow64!Wow64SystemServiceEx+0xd7
03 00000000`7424d286 : 00000000`00000000 00000000`741d1920 00000000`770f3128 00000000`7712c4f1 : wow64cpu!ServiceNoTurbo+0x2d
04 00000000`7424c69e : 00000000`00000000 00000000`00000000 00000000`74244b10 00000000`7ffe0030 : wow64!RunCpuSimulation+0xa
05 00000000`771243c3 : 00000000`002c3b20 00000000`00000000 00000000`77222e70 00000000`770f7550 : wow64!Wow64LdrpInitialize+0x42a1  Id: 2718.4d8 Suspend: 1 Teb: 00000000`7efd8000 Unfrozen# RetAddr           : Args to Child                                                           : Call Site
00 00000000`741d283e : 00000000`74b3a965 00000000`00000023 00000000`00000246 00000000`0373f30c : wow64cpu!CpupSyscallStub+0x9
01 00000000`7424d286 : 00000000`00000000 00000000`741d1920 00000000`00000000 00000000`00000000 : wow64cpu!WaitForMultipleObjects32+0x3b
02 00000000`7424c69e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : wow64!RunCpuSimulation+0xa
03 00000000`771898c4 : 00000000`00000000 00000000`7efdf000 00000000`7efd8000 00000000`00000000 : wow64!Wow64LdrpInitialize+0x42a2  Id: 2718.2078 Suspend: 1 Teb: 00000000`7efd5000 Unfrozen# RetAddr           : Args to Child                                                           : Call Site
00 00000000`741d283e : 00000000`74b38e63 00000000`00000023 00000000`00000246 00000000`03bcf9fc : wow64cpu!CpupSyscallStub+0x9
01 00000000`7424d286 : 00000000`00000000 00000000`741d1920 00000000`00000000 00000000`00000000 : wow64cpu!WaitForMultipleObjects32+0x3b
02 00000000`7424c69e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : wow64!RunCpuSimulation+0xa
03 00000000`771898c4 : 00000000`00000000 00000000`7efdf000 00000000`7efd5000 00000000`00000000 : wow64!Wow64LdrpInitialize+0x42a

    Windows x64系统为了兼容win32程序,加入了Wow64子系统。Wow子系统Hook win32的系统调用,在Wow64Cpu/Wow64/Wow64win三个dll中实现相应的系统调用功能。所以尽管calc.exe并不显示依赖这些dll,但是在windbg输出的调用栈中仍会找到这些模块信息。

    既然Wow64子系统只是Hook win32程序的API,那么他必然不会修改程序本身的实现,所以calc.exe的调用信息只是被隐藏在Wow64Cpu/Wow64/Wow64win这3个dll的背后。那么如何把他们暴露到阳光下?只要2条windbg命令就能实现:

0:003> .load wow64exts
0:003> !wow64exts.sw
Switched to Guest (WoW) mode

    wow64exts命令扩展随windbg一起发布,用于调试运行在Wow64子系统中的win32程序,默认并不加载,需要使用.load wow64exts加载。加载后通过命令!wow64exts.sw切换模式,切换后就像在x86系统上调试win32程序一样:

0:003:x86> ~*kb0  Id: 2718.1c98 Suspend: 1 Teb: 7efdb000 Unfrozen# ChildEBP RetAddr  Args to Child              
00 0017ef64 74b3790d 0017f068 00000000 00000000 USER32!NtUserGetMessage+0x15
01 0017ef80 00871cbc 0017f068 00000000 00000000 USER32!GetMessageW+0x33
02 0017fcfc 0088219a 00870000 00000000 00483faf calc!WinMain+0x878
03 0017fd8c 75d5343d 7efde000 0017fdd8 772e9802 calc!_initterm_e+0x1a1
04 0017fd98 772e9802 7efde000 77afdc5b 00000000 KERNEL32!BaseThreadInitThunk+0xe
05 0017fdd8 772e97d5 00882d6c 7efde000 00000000 ntdll_772b0000!__RtlUserThreadStart+0x70
06 0017fdf0 00000000 00882d6c 7efde000 00000000 ntdll_772b0000!_RtlUserThreadStart+0x1b1  Id: 2718.4d8 Suspend: 1 Teb: 7efd8000 Unfrozen# ChildEBP RetAddr  Args to Child              
00 0373f9ac 76dc171a 00000002 0373f9fc 00000001 ntdll_772b0000!ZwWaitForMultipleObjects+0x15
01 0373fa48 75d519fc 0373f9fc 0373fa70 00000000 KERNELBASE!WaitForMultipleObjectsEx+0x100
02 0373fa90 74b40882 00000002 7efde000 00000000 KERNEL32!WaitForMultipleObjectsExImplementation+0xe0
03 0373fae4 74b40b81 000000f4 0373fb44 ffffffff USER32!RealMsgWaitForMultipleObjectsEx+0x14d
04 0373fb00 71057910 00000001 0373fb44 00000000 USER32!MsgWaitForMultipleObjects+0x1f
05 0373fb4c 7105782f 00000000 00000000 00000000 gdiplus!BackgroundThreadProc+0x59
06 0373fb64 75d5343d 00832218 0373fbb0 772e9802 gdiplus!DllRefCountSafeThreadThunk+0x10
07 0373fb70 772e9802 00832218 74cbda33 00000000 KERNEL32!BaseThreadInitThunk+0xe
08 0373fbb0 772e97d5 7105781f 00832218 00000000 ntdll_772b0000!__RtlUserThreadStart+0x70
09 0373fbc8 00000000 7105781f 00832218 00000000 ntdll_772b0000!_RtlUserThreadStart+0x1b2  Id: 2718.2078 Suspend: 1 Teb: 7efd5000 Unfrozen# ChildEBP RetAddr  Args to Child              
00 03bcfa8c 72a3a41c 00000001 03bcfaec 00000001 ntdll_772b0000!ZwWaitForMultipleObjects+0x15
01 03bcfb34 75d5343d 00000000 03bcfb80 772e9802 WINMM!timeThread+0x3c
02 03bcfb40 772e9802 00000000 7404da03 00000000 KERNEL32!BaseThreadInitThunk+0xe
03 03bcfb80 772e97d5 72a3a3e0 00000000 00000000 ntdll_772b0000!__RtlUserThreadStart+0x70
04 03bcfb98 00000000 72a3a3e0 00000000 00000000 ntdll_772b0000!_RtlUserThreadStart+0x1b#  3  Id: 2718.2734 Suspend: 1 Teb: 7ef9d000 Unfrozen# ChildEBP RetAddr  Args to Child              
00 0287f8c0 00000000 00000000 00000000 00000000 ntdll_772b0000!RtlUserThreadStart

从这次windbg的输出中可以看到熟悉的模块名字,就连寄存器也以x86架构的形式输出:

0:003:x86> r
eax=771e9390 ebx=00000000 ecx=00000000 edx=00000000 esi=00000000 edi=00000000
eip=772c01e4 esp=0287f8bc ebp=00000000 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
ntdll_772b0000!RtlUserThreadStart:
772c01e4 89442404        mov     dword ptr [esp+4],eax ss:002b:0287f8c0=00000000

最后,再次执行!wow64exts.sw命令,windbg又切换回x64模式,输出的内容跟文章开头一样~

参考:windows Internal 6th

Debugging WOW64


http://chatgpt.dhexx.cn/article/uQH1uf5Z.shtml

相关文章

谈谈Windows Wow64

本文是《深入理解Windows操作系统 (第六版) 》关于64位Windows操心系统有关Wow64部分的读书笔记,因为之前很少有接触到关于Wow64的部分,记录一下。 Wow64是允许在64位Windows上执行32位x86应用程序的软件。它的实现方式是一组用户模式dll,外…

Windows WOW64 nativeapi 逆向详解,32程序兼容剖析

前言 windows有很多核心的原生api,其中包含sdk声明的和文档未声明的。主要由于ntdll.dll和win32u.dll(服务号0x1000-0x1FFF)导出。 WOW64 (Windows-on-Windows 64-bit)是一个Windows操作系统的子系统,用于模拟32位环境,使得32位执行程序在x64…

mysql版本wow64平台_WOW64最佳实现

WOW64简介 WOW64(Windows 32-bit On Windows 64-bit)是x64平台上运行win32应用程序的模拟器,它在系统层提供了中间层,将win32的系统调用转换成x64进行调用,并且将x64返回的结果转换成win32形式返回给win32程序。下图描述了win32程序如何在x64…

WOW64机制

WOW64: Windows On Windows64 是一种在64位OS中支持运行的32位应用程序的机制. 64位Windows中, 64位应用程序会加载64位的kernel32.dll, ntdll.dll, 32位应用程序会加载32位的kernel32.dll, ntdll.dll. WOW64则会将32位的dll文件的API请求重定向到64位的dll文件. 注意内核模式…

java for数组遍历数组_Java foreach操作(遍历)数组

语法: 我们分别使用 for 和 foreach 语句来遍历数组 运行结果: 练习: import java.util.Arrays; public class HelloWorld {public static void main(String[] args) {// 定义一个整型数组,保存成绩信息 int[] scores = { 89, 72, 64, 58, 93 }; // 对Arrays类对数组进行排…

【有趣的实验】JAVA 遍历数组的几种方式的耗时对比

一、前言 出于对遍历方式的耗时想法&#xff0c;是普通for循环、fori、foreach、迭代器 iterator、还是steam流的形式哪种耗时更少呢&#xff1f; 首先添加一个List 集合&#xff0c;这边采用ArraryList ArrayList<Integer> list new ArrayList<Integer>();list …

Java高逼格遍历数组的方式

在普通for循环遍历或取数组元素或做其他操作时&#xff0c;总会以将要超出数组最大索引作为循环结束的标志&#xff0c;也就是说每一次循环都要去判断此条件是否满足 而forEach强就强在它无需这一步流程&#xff0c;所以效率要高 但在今天我无意写出了一种这样的遍历方式&…

java遍历数组的三种方式

for循环遍历 用for循环遍历数组是很常见的一种方法&#xff0c;Java语言中通过数组的length属性可获得数组的长度。 package demo; publicclasstest{ public static void main(String[] args){ int [] array {1,2,3,4,5};for(int i 0;i < array.length;i){ System.out.print…

Java基础-遍历数组

Java基础-遍历数组 1、语法简介2、一维数组3、二维数组4、三维数组 1、语法简介 在Java中&#xff0c;对for语句的功能给予了扩充、加强&#xff0c;以便更好的遍历数组。 语法格式如下&#xff1a; for(声明循环变量:数组的名字){......... }其中&#xff0c;声明的循环变量…

JAVA 遍历数组求平均值与最大值

求平均值与最大值 实现前需要懂得如何获取数组长度实现数组遍历 例如&#xff1a; int[] array {2,3,6,8,18}; for(int i 0 ; i<array.length; i){ System.out.print(array[i] ","); } 输出结果&#xff1a;2,3,6,8,18 求最大值时则采用擂台制现默认一个数…

java遍历数组(Java遍历数组拿取对应的)

java中怎样遍历数组对象的值 int[] a {1,2,3}; for(int i0;i System.out.println(a[i]); }//定义一个string类型的一维数组 string[] namesnew string[5]; //为数组赋值 for (int i 0; i < names.length; i) { names[i]integer.tostring(i); //使用foreach遍历数组 int in…

java遍历数组最简洁的方法,java遍历数组的方式有哪些?

我们也了解Java也已经很久了&#xff0c;那今天小编想问大家是否知道java遍历数组的方式有哪些?是不是内心已经已经有答案了?让就跟着小编的步伐一起看看吧。 1. for循环遍历 这是最基本的遍历方式 通常遍历数组都是使用for循环来实现。遍历一维数组很简单&#xff0c;遍历二…

java中遍历数组方法

1循环遍历数组方法 在main主函数中给数组赋值即可调用该方法 public static void fun07(int[] array) {System.out.print("[");//输出一个左中括号if (array ! null) { //如果数组不为空&#xff0c;执行下面的语句for (int i 0; i < array.length; i) { /…

Java中数组遍历的五种方法

遍历&#xff1a;Stream遍历&#xff0c;循环遍历 //TODO 为Java提供的一种书签import java.util.Vector; import java.util.Enumeration; import java.util.Iterator; import java.util.Random;/*** 数组多种遍历偶数方法* * author 轩**/ public class Main {public static v…

Java:遍历数组的三种方法

1、for循环遍历数组 用for循环遍历数组是很常见的一种方法&#xff0c;Java语言中通过数组的length属性可获得数组的长度。 package demo;public class test {public static void main(String[] args) {int [] array {1,2,3,4,5};for(int i 0;i < array.length;i) {Syste…

java中数组遍历的三种方式

1.for循环遍历 通常遍历数组都是使用for循环来实现。遍历一维数组很简单&#xff0c;遍历二维数组需要使用双层for循环&#xff0c;通过数组的length属性可获得数组的长度。 2.Arrays工具类中toString静态方法遍历 利用Arrays工具类中的toString静态方法可以将一维数组转化为字…

Oracle--常用数据库对象(视图、序列、索引、同义词)详解

常见的数据库对象 对象描述表基本的数据存储集合&#xff0c;由行和列组成视图从表中抽出的逻辑上相关的数据集合序列提供有规律的数值索引提高查询的效率同义词给对象起别名 视图 什么是视图&#xff1f; 视图是一个 虚 表 \color{red}{虚表} 虚表视图建立在已有表的基础上…

Oracle【基础函数、视图、索引】

1. 认识oracle数据库 Oracle是非常强大的数据库软件。默认端口&#xff1a;1521。与MySQL不同的是&#xff0c;Oracle数据库的概念是一个操作系统装的就是一个大的数据库。一个数据库可以有很多个实例&#xff0c;每个实例占用一系列的进程和内存。通常一台机器只用一个实例。每…

主要是sql查询符合在圆形,多边形区域经纬度的数据

主要是sql查询符合在圆形&#xff0c;多边形区域经纬度的数据 查询 圆形 中心点 距离 drop table if exists demo; CREATE TABLE demo (id int(5) NOT NULL AUTO_INCREMENT COMMENT 主键,shop_name varchar(50) DEFAULT NULL COMMENT 商品名称,lng DECIMAL( 11, 8 ) DEFA…

mysql计算相关系数_用sql实现相关系数的计算

登录后查看更多精彩内容~ 您需要 登录 才可以下载或查看,没有帐号?立即注册 x 本帖最后由 静言_GRMC 于 2018-5-25 13:07 编辑 平时工作中要用到好多统计查询功能,一直用sql比较顺手,最近需要做相关系数方面的统计,发现除了Oracle自带了函数外,ms sql和mysql都没有自带计…