0%

南京邮电大学 RE-WxyVM2

WxyVM2

大概是要读这个程序里面的一段汇编代码,这段汇编代码非常长,连ida都无法反编译,但是非常有规律,可以通过写脚本来还原 这是初始化代码,估计是对加密的字符串进行还原的:

.text:00000000004005FE                 mov     cs:dword_694140, 9C06AA99h
.text:0000000000400608 mov cs:dword_694144, 0B4B2B03Fh
.text:0000000000400612 mov cs:dword_694148, 0C51F73CFh
.text:000000000040061C mov cs:dword_69414C, 223520F8h
.text:0000000000400626 mov cs:dword_694150, 0C0C53B9h
.text:0000000000400630 mov cs:dword_694154, 0B59C78EAh
.text:000000000040063A mov cs:dword_694158, 0F7DE2D34h
.text:0000000000400644 mov cs:dword_69415C, 0B27EEE2Ch

类似于下面这样的

.text:000000000048BAF1                 mov     edx, cs:dword_694174
.text:000000000048BAF7 mov eax, cs:dword_694178
.text:000000000048BAFD xor eax, edx
.text:000000000048BAFF mov cs:dword_694178, eax
.text:000000000048B93B                 movzx   eax, cs:byte_694116
.text:000000000048B93C add eax, 7Dh
.text:000000000048B93F mov cs:byte_694116, al
.text:000000000048B95C                 movzx   eax, cs:byte_694100
.text:000000000048B95C xor eax, 6Ah
.text:000000000048B95F mov cs:byte_694100, al
.text:000000000041DD09                 movzx   eax, cs:byte_69410F
.text:000000000041DD09 sub eax, 6Eh
.text:000000000041DD0C mov cs:byte_69410F, al

还有一种 我 mov 我 自 己

.text:000000000040093E                 movzx   eax, cs:byte_694114
.text:0000000000400945 mov cs:byte_694114, al

ida可以修改配置文件,这样就可以反编译了 byte_694100是字符串读入的起始地址 读取18h字节

.text:00000000004005CD                 call    _puts
.text:00000000004005D2 mov esi, offset byte_694100
.text:00000000004005D7 mov edi, offset format ; "%s"
.text:00000000004005DC mov eax, 0
.text:00000000004005E1 call _ssanf

694100~694117 查看汇编代码后发现很多操作都超出了这个内存的范围,而且最后也没有对这个内存进行任何修改,那么就应该直接舍去 先将所有汇编代码dump下来,用脚本筛掉垃圾代码

def get_string(line):
l = []
s = ""
for i in range(len(line)):
if(line[i] == ' ' or line[i] == ',' or i == len(line) - 1):#如果读取到了末尾
if(len(s) != 0):
l.append(s)
s = ""
else:
s = s + line[i]

return l

i = 0
f = open("code.dump", "r")
fout = open("decode.txt", "w")
#fout.write("Below is decoded code.\n(format:) addr [opt] num\n")
while(1):
line = f.readline()
i += 1
if(line == ""):
print("正常退出")
fout.close()
break
tab = get_string(line)#获取到一个汇编指令
if(tab[1] == "mov"):#如果是垃圾指令,就直接跳过
line = f.readline()
i += 1
line = f.readline()
i += 1
line = f.readline()
i += 1

elif(tab[1] == "movzx"):
addr = tab[3]
addr = "0x" + addr[8::]#获取地址信息
addr_num = int(addr, 16)
addr_num -= 6897920 #减去起始地址 得到偏移量
addr = str(addr_num)

line = f.readline()
i += 1

tab = get_string(line)

if(tab[1] != "mov"):#只有当这个指令不是mov的时候才进行判断,因为有一种垃圾指令是自己mov自己
if(tab[1] == "add"):
opt = "+="
elif(tab[1] == "xor"):
opt = "^="
elif(tab[1] == "sub"):
opt = "-="
else:
print("something goes wrong! " + tab[1] + " at :" + str(i))
break

s = tab[3]
# s = s[:-1:]
# s = "0x" + s

if(s[-1] == "h"):
s = s[:-1]
s = "0x" + s

s = str(int(s, 16) % 128)

line = f.readline()
i += 1
fout.write(addr + " " + opt + " " + s + "\n")

else:
print("something goes wrong! " + tab[1] + " at :" + str(i))
break

f.close()
fout.close()

得到类似于如下的数据

23 += 11
3 += 31
5 += 78
23 += 109
2 -= 25
1 -= 48
11 += 123
13 ^= 38
23 ^= 89
12 += 3
11 -= 5
13 += 75
4 ^= 72
5 -= 88
4 -= 107
0 ^= 60
23 ^= 27

再写python进行逆向计算:

def get_string(line):
l = []
s = ""
for i in range(len(line)):
if(line[i] == ' ' ):#如果读取到了末尾
if(len(s) != 0):
l.append(s)
s = ""
else:
s = s + line[i]
if(len(s) != 0):
l.append(s)

return l

enc =[0xC0,0x85,0xF9,0x6C,0xE2,0x14,0xBB,0xe4,0xd,0x59,0x1c,0x23,0x88,0x6e,0x9b,0xca,0xba,0x5c,0x37,0xfff,0x48,0xd8,0x1f,0xab,0xa5]

f = open("decode.txt", "r")
all = []

i = -1
while(1):
line = f.readline()
if(line == ""):
break
i += 1
all.append(line)

while(i >= 0):
line = all[i]
tab = get_string(line)
i -= 1

if(tab[1] == "+="):
enc[int(tab[0])] -= int(tab[2])
elif(tab[1] == "-="):
enc[int(tab[0])] += int(tab[2])
else:
enc[int(tab[0])] ^= int(tab[2])
enc[int(tab[0])] %= 128
ans = ""
for c in enc:
ans = ans + chr(c)
print(ans)