我试图理解为什么使用Windbg挂起安装文件,但我无法阻止执行。
作为背景,我已经能够在同一台PC上安装这个程序,但出于某种原因我已经卸载了,现在我无法重新安装它(我试图清理旧安装中的所有内容) ,包括注册表)。现在这个setup.exe启动并在正在运行的进程中保持空闲状态而不做任何事情。
但是让我们回到实际的问题。我是第一次尝试使用Windbg(我在DOS时只用了旧的8086调试练习:-),所以如果我问一些直截了当的话,请耐心等待。)
我已经跟踪了代码,直到我有一个RET代码。我能够在RET指令处停止调试器,但是一旦我“进入”RET,执行就会开始并且不会停止,而我期望它只是转到前一个CALL之后的指令。从我看到的东西来看,似乎在RET之后执行到了其他地方......怎么可能呢?此外,在RET之前有一个我不完全理解的SYSCALL ......它会产生影响吗?
这是我目前正在审查的代码部分:
ntdll!NtTerminateThread:
00007ff9`fc8b5b20 4c8bd1 mov r10,rcx
00007ff9`fc8b5b23 b853000000 mov eax,53h
00007ff9`fc8b5b28 f604250803fe7f01 test byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],1
00007ff9`fc8b5b30 7503 jne ntdll!NtTerminateThread+0x15 (00007ff9`fc8b5b35)
00007ff9`fc8b5b32 0f05 syscall
00007ff9`fc8b5b34 c3 ret
00007ff9`fc8b5b35 cd2e int 2Eh
00007ff9`fc8b5b37 c3 ret
我被困在第一条RET指令处,地址为5b34。 这时,这是堆栈调用:
00000000`0203fc38 00007ff9`fc86c63e ntdll!NtTerminateThread+0x14
00000000`0203fc40 00007ff9`fc8d903a ntdll!RtlExitUserThread+0x4e
00000000`0203fc80 00007ff9`fc86c5c5 ntdll!DbgUiRemoteBreakin+0x5a
00000000`0203fcb0 00000000`00000000 ntdll!RtlUserThreadStart+0x45
所以我的理解是执行应该继续在地址00007ff9`fc86c63e。但是,即使我在这个地址添加了一个BP,或者我只是寻找一个跟踪,执行仍然继续并继续运行一些空闲循环,直到我点击windbg中的“暂停”按钮,然后它在一个完全不同的地址恢复
如果寄存器是相关的,以下是其中一些:
rax: 353000
rbx: 0
rcx: 0
rdx: 0
rsp: 203fc38
rdi: 7ff9c8d8fe0
rip: 7ff9fc8b5b34
所以,最终,我错在哪里?如何在RET之后查看代码的位置?
提前感谢您的帮助,
鲍勃
答案 0 :(得分:0)
当线程退出执行时不会返回到返回地址
系统可以自由安排在流程中准备好的另一个线程
堆栈在堆栈上显示NtTerminateThread,它是一个不返回的函数
__declspec noreturn foo(...);
btw当你说它去别的地方你是说应用程序继续运行并且没有终止,如果这样点击ctrl + break并检查其他线程正在做什么
即如果usermode ~*kb
应显示所有线程callstack
回答关于它去哪里的评论
process
是collection of threads
每个线程都有一个堆栈,每个线程都有一点时间来执行from the scheduler (thread quantum)
优先级较低的每个帖子都可以被threads xxxx ,yyy ,zzz with higher priorities
by interrupts by apcs , dpcs etc
当一个线程完成了它的量子或者被一些vip行列队先发生在这条可怜的线程走的路上
一个陷阱_KTRAP
,这个可怜的螺纹位置EIP
被填入其中并放入一个等待的螺纹路障中
当贵宾行列的尘埃落定时,警察打开路障,让可怜的线程从停止的地方走出来
对于这些血腥细节,您可能需要内核调试设置,可能需要从内核调试器控制您的进程
当你点击返回操作系统时,看到线程已经死了并且没有返回地址
所以它检查!ready
个线程并选择最高优先级的线程并为它提供一个量子来享受
所以在点击返回地址之前检查你的app中所有其他线程正在做什么,在感兴趣的线程上设置适当的中断并在另一个线程执行其量程时点击返回,你的中断将被击中
答案 1 :(得分:0)
您正在查看错误的帖子!
从您提供的部分输出看起来您正在附加到正在运行的进程(而不是从调试器启动它)。为了进入一个正在运行的进程,调试器将一个线程注入到目标进程中,该进程基本上包含一个硬编码的int 3
指令而不是更多。
它是通过调用ntdll!RtlpCreateUserThreadEx
(内部未记录的CreateRemoteThread
原始并行)提供ntdll!DbgUiRemoteBreakin
作为新线程的起始地址来实现的。
此合成线程的唯一目的是生成断点异常。此异常导致操作系统停止运行目标进程并将控制权传递给调试器。在它这样做之后不再需要它并且它自杀了。
此时您应该做的事情可能是使用~s命令切换到您感兴趣的线程,设置断点然后继续执行。
如果尝试单步执行此合成线程,它将结束,然后该过程将继续执行它在您进入之前所做的任何事情,这几乎与您想要的相反,
这个堆栈意味着什么:
00000000`0203fc38 00007ff9`fc86c63e ntdll!NtTerminateThread+0x14 00000000`0203fc40 00007ff9`fc8d903a ntdll!RtlExitUserThread+0x4e 00000000`0203fc80 00007ff9`fc86c5c5 ntdll!DbgUiRemoteBreakin+0x5a 00000000`0203fcb0 00000000`00000000 ntdll!RtlUserThreadStart+0x45
ntdll!RtlUserThreadStart
是所有用户模式线程的真实用户模式入口点,您可以看到它刚刚调用ntdll!DbgUiRemoteBreakin
,之后您继续一点直到线程最终结束。