Assembly 反汇编程序如何从内存中提取操作码?

Assembly 反汇编程序如何从内存中提取操作码?,assembly,pykd,Assembly,Pykd,我想弄清楚反汇编程序是如何工作的。具体来说,内存中的内容如何映射到相应的汇编语言操作码 下面是内存中的内容,第一列地址: 773eed5c 50 ff 15 0c 17 3a 77 90-90 90 90 90 8b ff 55 8b P....:w.......U. 773eed6c ec 51 51 83 7d 10 00 74-38 ff 75 10 8d 45 f8 50 .QQ.}..t8.u..E.P 773eed7c e8 14 d7 ff ff 85 c0 74-24

我想弄清楚反汇编程序是如何工作的。具体来说,内存中的内容如何映射到相应的汇编语言操作码

下面是内存中的内容,第一列地址:

773eed5c  50 ff 15 0c 17 3a 77 90-90 90 90 90 8b ff 55 8b  P....:w.......U.
773eed6c  ec 51 51 83 7d 10 00 74-38 ff 75 10 8d 45 f8 50  .QQ.}..t8.u..E.P
773eed7c  e8 14 d7 ff ff 85 c0 74-24 56 ff 75 fc ff 75 0c  .......t$V.u..u.
773eed8c  ff 75 08 e8 ab ff ff ff-83 7d 10 00 8b f0 74 0a  .u.......}....t.
773eed9c  8d 45 f8 50 ff 15 9c 15-3a 77 8b c6 5e c9 c2 0c  .E.P....:w..^...
773eedac  00 83 65 fc 00 eb d2 90-90 90 90 90 8b ff 55 8b  ..e...........U.
773eedbc  ec 57 e8 c7 d6 ff ff 8b-4d 0c 6a 34 5f 03 c7 0f  .W......M.j4_...
773eedcc  b7 00 40 40 03 c9 3b c8-0f 82 07 e5 00 00 56 e8  ..@@..;.......V.
以及相应的反汇编结果、指令的第一列内存地址、第二列操作码、其余列汇编指令:

0x773eed5c 50 push    eax
0x773eed63 90 nop
0x773eed65 90 nop
0x773eed67 90 nop
0x773eed6a 55 push    ebp
0x773eed6d 51 push    ecx
0x773eed6f 837d1000 cmp     dword ptr [ebp+10h],0 ss:0023:056cfa8c=778237eb
0x773eed7c e814d7ffff call    kernel32!Basep8BitStringToDynamicUnicodeString (773ec495)
现在我可以看到操作码
e814d7ffff
在内存中(
e8 14 d7 ff

但是如何解释内存地址中的内容?
push eax
的操作码和连续的
nop
s如何映射到内存内容
0c15ff50 90773a17 90909090 8b55ff8b

更新:

我上面给出的拆解结果不正确。正确的结果(如下所示)非常适合内存中的内容:

0x773eed5c 50 push    eax
0x773eed5d ff150c173a77 call    dword ptr [kernel32+0x170c (773a170c)] ds:0023:773a170c={ntdll!RtlExitUserThread (777ef608)}
0x773eed63 90 nop
0x773eed64 90 nop
0x773eed65 90 nop
0x773eed66 90 nop
0x773eed67 90 nop
0x773eed68 8bff mov     edi,edi
0x773eed6a 55 push    ebp
0x773eed6b 8bec mov     ebp,esp
0x773eed6d 51 push    ecx
0x773eed6e 51 push    ecx
0x773eed6f 837d1000 cmp     dword ptr [ebp+10h],0 ss:0023:0447fc24=778237eb
0x773eed73 7438 je      kernel32!OpenFileMappingA+0x45 (773eedad) [br=1]
0x773eed75 ff7510 push    dword ptr [ebp+10h]  ss:0023:0447fc24=778237eb
0x773eed78 8d45f8 lea     eax,[ebp-8]
0x773eed7b 50 push    eax
0x773eed7c e814d7ffff call    kernel32!Basep8BitStringToDynamicUnicodeString (773ec495)

有关我的错误的详细信息:我正在使用WinDbg开发一个工具。关于它的
disasm
模块的文档没有涵盖细节,所以我对
disasm.jumprel
函数使用了错误的参数,这导致了不完整的反汇编结果。

实际上很简单

看看:

这是一个x86指令集参考

如果您查找“PUSH AX”,您将看到操作码是
50
。如果您查找“NOP”,您将看到它的操作码是
90

因此,所发生的事情是您拥有每个操作码的外观集合(
50
=
PUSH AX
90
=
NOP
,等等)。有些操作码比其他操作码需要更多的参数。
调用
操作码有4种模式,第一种模式,
E8
,用于“近指针”

现在,x86有不同的操作模式(16b、32b、64b),因此它重用相同的操作码,但调整不同模式的参数。这是反汇编程序需要提前知道的。因为“近指针”在16b、32b和64b模式下是不同的(除其他外,它们占用更多空间)

但最终,一个简单的反汇编程序会查找其当前的操作码,根据操作码消耗尽可能多的字节,然后为该内存创建适当的汇编指令

更复杂的反汇编程序理解更高级的语言,可以指出代码无法访问的区域(例如,它可以跟踪跳转、调用和分支,并知道哪些代码不能反汇编)


反汇编程序可能会变得非常复杂,但简单的反汇编程序很简单。

实际上非常简单

看看:

这是一个x86指令集参考

如果您查找“PUSH AX”,您将看到操作码是
50
。如果您查找“NOP”,您将看到它的操作码是
90

因此,所发生的事情是您拥有每个操作码的外观集合(
50
=
PUSH AX
90
=
NOP
,等等)。有些操作码比其他操作码需要更多的参数。
调用
操作码有4种模式,第一种模式,
E8
,用于“近指针”

现在,x86有不同的操作模式(16b、32b、64b),因此它重用相同的操作码,但调整不同模式的参数。这是反汇编程序需要提前知道的。因为“近指针”在16b、32b和64b模式下是不同的(除其他外,它们占用更多空间)

但最终,一个简单的反汇编程序会查找其当前的操作码,根据操作码消耗尽可能多的字节,然后为该内存创建适当的汇编指令

更复杂的反汇编程序理解更高级的语言,可以指出代码无法访问的区域(例如,它可以跟踪跳转、调用和分支,并知道哪些代码不能反汇编)


反汇编程序可以变得非常复杂,但简单的反汇编程序很简单。

似乎确实缺少一些东西

50                push eax
ff 15 0c 17 3a 77 call [0x0c173a77] ; where did this thing go?
90                nop
90                nop
90                nop
90                nop
90                nop
8b ff             mov edi, edi  ; wut?
55                push ebp      ; this looks like the beginning of a function
8b ec             mov ebp, esp
51                push ecx
51                push ecx
83 7d 10 00       cmp [ebp + 10], 0

我是手工拆卸的,可能是我弄错了。这个代码很奇怪。你对它的分解更奇怪,我不知道它是怎么发生的。

似乎确实缺少一些东西

50                push eax
ff 15 0c 17 3a 77 call [0x0c173a77] ; where did this thing go?
90                nop
90                nop
90                nop
90                nop
90                nop
8b ff             mov edi, edi  ; wut?
55                push ebp      ; this looks like the beginning of a function
8b ec             mov ebp, esp
51                push ecx
51                push ecx
83 7d 10 00       cmp [ebp + 10], 0

我是手工拆卸的,可能是我弄错了。这个代码很奇怪。您对它的拆卸更为奇怪,我不知道它是如何发生的。

阅读您的体系结构说明手册;每条指令对应一个数值。x86指令集有文档记录(请参阅英特尔软件开发人员手册),PE(exe/dll)格式也有文档记录。如果你想编写一个反汇编程序,生成像你在问题中所展示的那样的输出,你需要很好地掌握这两个信息源。在你的代码中,
push eax
nop
不是连续的,它们的地址相差相当多的字节。您使用的反汇编程序/内存查看器是什么(乍一看,它看起来像WinDBG),为什么要将内存转储为DWORD而不是单字节?@KerrekSB是的,我了解这一部分,让我困惑的是,这些数字是如何放在内存中的,反汇编程序是如何知道这些数字的位置并从内存中提取这些操作码的。好吧,假设这一切都是有意义的,为什么反汇编中遗漏了这么多呢?请阅读您的体系结构说明手册;每条指令对应一个数值。x86指令集有文档记录(请参阅英特尔软件开发人员手册),PE(exe/dll)格式也有文档记录。如果你想编写一个反汇编程序,生成像你在问题中所展示的那样的输出,你需要很好地掌握这两个信息源。在你的代码中,
push eax
nop
不是连续的,它们的地址相差相当多的字节。您使用的是什么反汇编程序/内存查看器(乍一看,它看起来像WinDBG),为什么要将内存转储为DWORD而不是单个字节?@KerrekSB是的,我知道这部分,什么