import
pefile
import
struct
from
capstone.x86
import
*
from
capstone
import
*
from
unicorn
import
*
from
unicorn.x86_const
import
*
from
binascii
import
*
def
u32(data):
return
struct.unpack(
"I"
, data)[
0
]
def
p32(num):
return
struct.pack(
"I"
, num)
def
patch(image, image_base, address, patch_data):
i
=
0
for
b
in
patch_data:
image[address
-
image_base
+
i]
=
b
i
+
=
1
def
get_reloc_data_rva(pefile_struct):
reloc_table_num
=
pefile.DIRECTORY_ENTRY[
'IMAGE_DIRECTORY_ENTRY_BASERELOC'
]
reloc_table
=
pe.OPTIONAL_HEADER.DATA_DIRECTORY[reloc_table_num]
reloc_table_rva
=
reloc_table.VirtualAddress
reloc_table_size
=
reloc_table.Size
print
(f
'重定位表RAV:{reloc_table_rva:#x},重定位表大小:{reloc_table_size:#x}'
)
relocations
=
pe.parse_relocations_directory(reloc_table_rva, reloc_table_size)
reloc_data_rva
=
[]
for
i
in
relocations:
for
j
in
i.entries:
reloc_data_rva.append(j.rva)
return
reloc_data_rva
def
get_intruction_start_rva(memory_data, reloc_data_rva, ImageBase):
branch
=
[
"JZ"
,
"JP"
,
"JO"
,
"JS"
,
"JG"
,
"JB"
,
"JA"
,
"JL"
,
"JE"
,
"JNZ"
,
"JNP"
,
"JNO"
,
"JNS"
,
"JLE"
,
"JNB"
,
"JBE"
,
"JGE"
,
"JNE"
,
"JAE"
]
b
=
3
for
i
in
range
(
3
):
code
=
memory_data[reloc_data_rva
-
b: reloc_data_rva
-
b
+
40
]
if
b
=
=
3
and
code[
0
] !
=
0x66
:
b
=
b
-
1
continue
b
=
b
-
1
try
:
ins
=
md.disasm(code, ImageBase
+
reloc_data_rva
-
b
-
1
)
ins_1
=
next
(ins)
ins_2
=
next
(ins)
ins.close()
except
StopIteration:
continue
if
(ins_1.mnemonic
=
=
'cmp'
or
ins_1.mnemonic
=
=
'test'
)
and
ins_2.mnemonic.upper()
in
branch \
and
len
(ins_1.operands)
=
=
2
and
ins_1.operands[
0
].
type
=
=
X86_OP_MEM
and
ins_1.operands[
1
].
type
=
=
X86_OP_IMM:
return
ins_1.address
-
0x10000000
return
0
filename
=
'bf3e495f43a6b333b10ae69667304cfd2c87e9100de9d31365671c7b6b93132e'
pe
=
pefile.PE(filename, fast_load
=
True
)
memory_mapped_image
=
bytearray(pe.get_memory_mapped_image())
ImageBase
=
pe.OPTIONAL_HEADER.ImageBase
print
(
'[+] Map PE'
)
BASE
=
0x10000000
STACK_ADDR
=
0x400000
STACK_SIZE
=
1024
*
1024
mu
=
Uc(UC_ARCH_X86, UC_MODE_32)
mu.mem_map(BASE,
1024
*
1024
)
mu.mem_map(STACK_ADDR, STACK_SIZE)
r_esp
=
STACK_ADDR
+
STACK_SIZE
/
/
2
mu.reg_write(UC_X86_REG_ESP, STACK_ADDR
+
STACK_SIZE
/
/
2
)
mu.mem_write(
0x10000000
,pe.get_memory_mapped_image())
md
=
Cs(CS_ARCH_X86, CS_MODE_32)
md.detail
=
True
instruction_3
=
[]
def
hook_code(mu, address, size, userdata):
print
(f
'>>> Tracing instruction at {address:#x}, instruction size = {size:#x}'
)
r_esp
=
mu.reg_read(UC_X86_REG_ESP)
count
=
u32(mu.mem_read(r_esp
+
4
,
4
))
print
(f
'count is {count}'
)
if
count
=
=
2
:
instruction_3.append(address)
mu.emu_stop()
try
:
exit()
except
BaseException as e:
print
(e)
count
=
count
+
1
mu.mem_write(r_esp
+
4
, p32(count))
mu.hook_add(UC_HOOK_CODE, hook_code)
def
simulate_execute(ins_addr_rva):
mu.mem_write(r_esp
+
4
, p32(
0
))
mu.emu_start(ins_addr_rva
+
ImageBase,
0x100066E6
)
reloc_data_rva
=
get_reloc_data_rva(pe)
ins_addr_rva_all
=
[]
count
=
0
for
rva
in
reloc_data_rva:
ins_addr_rva
=
get_intruction_start_rva(memory_mapped_image, rva, ImageBase)
if
ins_addr_rva !
=
0
:
ins_addr_rva_all.append(ins_addr_rva)
simulate_execute(ins_addr_rva)
code
=
memory_mapped_image[ins_addr_rva:ins_addr_rva
+
40
]
ins
=
md.disasm(code, ImageBase
+
ins_addr_rva)
ins_1
=
next
(ins)
ins_2
=
next
(ins)
try
:
ins_3
=
next
(ins)
ins_3_address
=
ins_3.address
except
:
ins_3_address
=
0
ins.close()
if
instruction_3[count]
=
=
ins_3_address:
size
=
ins_1.size
+
ins_2.size
assembly
=
b
'\x90'
*
size
patch(memory_mapped_image, ImageBase, ImageBase
+
ins_addr_rva, assembly)
else
:
size
=
instruction_3[count]
-
ins_1.address
assembly
=
b
'\x90'
*
size
patch(memory_mapped_image, ImageBase, ImageBase
+
ins_addr_rva, assembly)
count
=
count
+
1
for
section
in
pe.sections:
print
(f
'{section.Name}, VirtualAddress: {section.VirtualAddress:#x}, '
f
'Size: {section.SizeOfRawData:#x}, 文件偏移: {section.PointerToRawData:#x}'
)
pe.set_bytes_at_rva(section.VirtualAddress,
bytes(memory_mapped_image[section.VirtualAddress:section.VirtualAddress
+
section.SizeOfRawData]))
print
(
'[+] Save to file '
+
'1.bin'
)
pe.write(
'1.bin'
)