该位置不应该为空或具有除汇编指令之外的其他值...?
答案是不”。正如作者在文章中所说,这个二进制文件是自我修改的:
在这个阶段,您可能已经正确地假设示例修改了这些说明以便正确地达到0x401101
.
...
在示例的 PE 标头中发现了另一个自修改代码的迹象。该.text
部分,且该计划的切入点所在,是可写的。
任何尝试拆卸从字节0x40107C
到0x40107C+0x79
会引起错误和不义的汇编指令。因此,我们应该了解操作这些字节的函数。
了解修改功能
正如您已经注意到的,这是负责修改此范围内字节的代码:
loc_401039:
mov bl, [eax]
xor bl, dl
add bl, 22h
mov [eax], bl
inc eax
cmp eax, ecx
jl short loc_401039
让我们使用伪代码来了解它是如何工作的:
start_addr = 0x0x40107c
end_addr = 0x40107c + 0x79 = 0x4010f5
key = 0x??
for addr in range(start_addr, end_addr+1):
# setByte (address, new_value); getByte (address)
setByte(addr, (getByte(addr)^key)+0x22)
因此,此范围内的每个字节都与某个键进行异或0x22
运算,然后添加到结果中。
示范
剧透警报!
下一部分包含有关答案的剧透
您所附的文章包含正确密钥的解决方案,您应该在 XOR 操作中使用该解决方案来修改字节。我将在以下示例中使用此密钥。
关键是(悬停查看):
0xa2
让我们尝试自己解密这些字节。我将为此使用radare2,但您可以使用任何其他您喜欢的解决方案。
首先,让我们复制这个挑战,因为我们要编辑二进制文件:
$ cp greek_to_me.exe modified_greek_to_me.exe
现在在写模式下用radare2打开二进制文件:
$ r2 -w modified_greek_to_me.exe
[0x00401000]>
让我们努力0x40107c
,看看它看起来像我们修改前的字节有:
[0x00401000]> s 0x40107c
[0x0040107c]> pd 10
0x0040107c 33e1 xor esp, ecx
0x0040107e c49911068116 les ebx, [ecx + 0x16810611]
0x00401084 f0 invalid
0x00401085 329fc4911706 xor bl, byte [edi + 0x61791c4]
0x0040108b 8114f0068115. adc dword [eax + esi*8], 0xf1158106
0x00401092 c4911a06811b les edx, [ecx + 0x1b81061a]
╭─< 0x00401098 e206 loop 0x4010a0
│ 0x0040109a 8118f2068119 sbb dword [eax], 0x198106f2
╰─> 0x004010a0 f1 int1
0x004010a1 06 push es
我在这个地址打印了 10 个操作码。如您所见,这些说明毫无意义,因为在当前状态下,它们不应被拆卸。
这是0x79
来自该地址的字节在十六进制中的样子:
[0x0040107c]> px 0x79
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
0x0040107c 33e1 c499 1106 8116 f032 9fc4 9117 0681 3........2......
0x0040108c 14f0 0681 15f1 c491 1a06 811b e206 8118 ................
0x0040109c f206 8119 f106 811e f0c4 991f c491 1c06 ................
0x004010ac 811d e606 8162 ef06 8163 f206 8160 e3c4 .....b...c...`..
0x004010bc 9961 0681 66bc 0681 67e6 0681 64e8 0681 .a..f...g...d...
0x004010cc 659d 0681 6af2 c499 6b06 8168 a906 8169 e...j...k..h...i
0x004010dc ef06 816e ee06 816f ae06 816c e306 816d ...n...o.
现在我们要对0x79
字节进行异或0x40107c
,然后添加0x22
到每个字节。我们可以使用radare2轻松做到这一点。
首先,我们应该定义我们想要操作的块大小,在我们的例子中它是 0x79:
[0x0040107c]> b?
|Usage: b[f] [arg]
Get/Set block size
| b display current block size
| b 33 set block size to 33
...
...
[0x0040107c]> b 0x79
添加?
到radare2 命令将显示有关该命令及其子命令的帮助
现在,让我们对来自0x40107c
to的字节进行异或0x40107c + block_size
,然后添加0x22
到每个字节中:
[0x0040107c]> wo?
|Usage: wo[asmdxoArl24] [hexpairs] @ addr[!bsize]
...
| woa [val] += addition (f.ex: woa 0102)
...
| wox [val] ^= xor (f.ex: wox 0x90)
[0x0040107c]> wox 0xa2
[0x0040107c]> woa 0x22
现在我们的字节被修改了。让我们看看它们在十六进制模式下的样子:
[0x0040107c]> px 0x79
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
0x0040107c b365 885d d5c6 45d6 74b2 5f88 55d7 c645 .e.]..E.t._.U..E
0x0040108c d874 c645 d975 8855 dac6 45db 62c6 45dc .t.E.u.U..E.b.E.
0x0040109c 72c6 45dd 75c6 45de 7488 5ddf 8855 e0c6 r.E.u.E.t.]..U..
0x004010ac 45e1 66c6 45e2 6fc6 45e3 72c6 45e4 6388 E.f.E.o.E.r.E.c.
0x004010bc 5de5 c645 e640 c645 e766 c645 e86c c645 ]..E.@.E.f.E.l.E
0x004010cc e961 c645 ea72 885d ebc6 45ec 2dc6 45ed .a.E.r.]..E.-.E.
0x004010dc 6fc6 45ee 6ec6 45ef 2ec6 45f0 63c6 45f1 o.E.n.E...E.c.E.
0x004010ec 6fc6 45f2 6dc6 45f3 00 o.E.m.E..
让我们拆开它,看看现在组装是否有意义:
[0x0040107c]> pD 0x79
0x0040107c b365 mov bl, 0x65 ; 'e' ; 101
0x0040107e 885dd5 mov byte [ebp - 0x2b], bl
0x00401081 c645d674 mov byte [ebp - 0x2a], 0x74 ; 't' ; 116
0x00401085 b25f mov dl, 0x5f ; '_' ; 95
0x00401087 8855d7 mov byte [ebp - 0x29], dl
0x0040108a c645d874 mov byte [ebp - 0x28], 0x74 ; 't' ; 116
0x0040108e c645d975 mov byte [ebp - 0x27], 0x75 ; 'u' ; 117
0x00401092 8855da mov byte [ebp - 0x26], dl
0x00401095 c645db62 mov byte [ebp - 0x25], 0x62 ; 'b' ; 98
0x00401099 c645dc72 mov byte [ebp - 0x24], 0x72 ; 'r' ; 114
0x0040109d c645dd75 mov byte [ebp - 0x23], 0x75 ; 'u' ; 117
0x004010a1 c645de74 mov byte [ebp - 0x22], 0x74 ; 't' ; 116
0x004010a5 885ddf mov byte [ebp - 0x21], bl
0x004010a8 8855e0 mov byte [ebp - 0x20], dl
0x004010ab c645e166 mov byte [ebp - 0x1f], 0x66 ; 'f' ; 102
0x004010af c645e26f mov byte [ebp - 0x1e], 0x6f ; 'o' ; 111
0x004010b3 c645e372 mov byte [ebp - 0x1d], 0x72 ; 'r' ; 114
0x004010b7 c645e463 mov byte [ebp - 0x1c], 0x63 ; 'c' ; 99
0x004010bb 885de5 mov byte [ebp - 0x1b], bl
0x004010be c645e640 mov byte [ebp - 0x1a], 0x40 ; '@' ; 64
0x004010c2 c645e766 mov byte [ebp - 0x19], 0x66 ; 'f' ; 102
0x004010c6 c645e86c mov byte [ebp - 0x18], 0x6c ; 'l' ; 108
0x004010ca c645e961 mov byte [ebp - 0x17], 0x61 ; 'a' ; 97
0x004010ce c645ea72 mov byte [ebp - 0x16], 0x72 ; 'r' ; 114
0x004010d2 885deb mov byte [ebp - 0x15], bl
0x004010d5 c645ec2d mov byte [ebp - 0x14], 0x2d ; '-' ; 45
0x004010d9 c645ed6f mov byte [ebp - 0x13], 0x6f ; 'o' ; 111
0x004010dd c645ee6e mov byte [ebp - 0x12], 0x6e ; 'n' ; 110
0x004010e1 c645ef2e mov byte [ebp - 0x11], 0x2e ; '.' ; 46
0x004010e5 c645f063 mov byte [ebp - 0x10], 0x63 ; 'c' ; 99
0x004010e9 c645f16f mov byte [ebp - 0xf], 0x6f ; 'o' ; 111
0x004010ed c645f26d mov byte [ebp - 0xe], 0x6d ; 'm' ; 109
0x004010f1 c645f300 mov byte [ebp - 0xd], 0
事实上,现在我们能够看到所有这些mov
构建标志的指令:)