Zprotect1.4-1.6patchKEY脱壳

 对于ZProtect 1.4.x版本的系列软件,只要有其一个可用的机器码和key就可实现完美脱壳。

海城网站建设公司创新互联建站,海城网站设计制作,有大型网站制作公司丰富经验。已为海城上千余家提供企业网站建设服务。企业网站搭建\成都外贸网站建设公司要多少钱,请找那个售后服务好的海城做网站的公司定做!

 

对于ZProtect 目前版本(ZP1.60)加壳的所有软件,只要有其一个可用的机器码和key就可实现完美脱壳。

 

假设已有一个可用的机器码和KEY:
机器码:AAAA-BBBB-CCCC-DDDD
序列号:B131FA844E0E9A7F32810DD67B9C4DC086EB

 

脚本流程:
1,寻找OEP断点。这个原理很简单,所谓的ESP平衡定律就是了。
2,对机器码进行补丁。zprotect用DeviceIoControl函数获取机器码相关,只要对该函数设置断点即可。当提示需输入机器号的前8位时,本例中,输入AAAABBBB,后8位即为CCCCDDDD。
3,修复IAT。本版本中IAT的起始和结束部分仍然需要手动填入。

4,用loadpe和IMR修复即可。

 

脚本内容:


BC
BPMC
BPHWC
call VARSINIT
//pause

sti
FIND_OEP:
mov EipForOep_1, eip
mov EipForOep_1, [EipForOep_1]
and EipForOep_1, 0ff
cmp EipForOep_1, 60
jne OEP_NEXT
sti
mov bpforoep, esp
jmp HWIDPatchStart

OEP_NEXT:
sto
jmp FIND_OEP

HWIDPatchStart:
////////////////////

HWID_PATCH:
bphws DeviceIoControl, "x"
bp DeviceIoControl
bphws VirtualAlloc, "x"
bp VirtualAlloc
esto
////////////////////
HWID_PATCH_CHECK_NEXT:
cmp eip, VirtualAlloc
jne HWID_PATCH_2
bphwc
bc
mov A_SIZE, [esp+08]
rtr
mov A_ADDRESS, eax
bphws DeviceIoControl, "x"
bp DeviceIoControl
bphws VirtualAlloc, "x"
bp VirtualAlloc
HWID_PATCH_CHECK_NEXT_ZHW: //zenghw add
esto
////////////////////
FIND_STRING:
mov tempdata,[esp]//zenghw add
cmp tempdata,77DA9559
je HWID_PATCH_CHECK_NEXT_ZHW
cmp eip, DeviceIoControl
je HWID_PATCH_2
find A_ADDRESS, #0FB?542410E9#
cmp $RESULT, 00
je HWID_PATCH_CHECK_NEXT
mov A_ADDRESS, $RESULT
inc A_ADDRESS
mov A_ADDRESS_BAK, $RESULT
mov dll, 01
add A_ADDRESS, 04
gci A_ADDRESS, DESTINATION
cmp $RESULT, 00
sub A_ADDRESS, 04
je FIND_STRING
mov ABC, $RESULT
cmp [ABC+03], 1124, 02 
jne FIND_STRING
add ABC, 05
cmp [ABC], E8, 01
jne FIND_STRING_B
mov call, 01
////////////////////
FIND_STRING_B:
gci ABC, DESTINATION
cmp $RESULT, 00
sub ABC, 05
je FIND_STRING
mov ABC, $RESULT
cmp call, 01
je FIND_STRING_C
cmp [ABC], 30, 01
jne FIND_STRING
////////////////////
FIND_STRING_C:
mov A_ADDRESS, A_ADDRESS_BAK
jmp HWID_PATCH_2

jmp HWID_PATCH
////////////////////
HWID_PATCH_2:
bphwc
bc
cmp dll, 01
jne HWID_PATCH_2_A
gmemi A_ADDRESS, MEMORYBASE
mov VMBASE, $RESULT
mov $RESULT, A_ADDRESS
jmp found
////////////////////
HWID_PATCH_2_A:
mov EXTRA, [esp]
gmemi EXTRA, MEMORYBASE
mov EXTRA, $RESULT
rtu
gmemi eip, MEMORYBASE
cmp EXTRA, $RESULT
jne VM
gmemi eip, MEMORYBASE
mov EXTRA_2, $RESULT
cmp [EXTRA_2], 5A4D, 02
jne VM
rtr
mov baceip, eip
////////////////////
SELFTEST:
sti
cmp eip, baceip
je SELFTEST
////////////////////
VM:
gmemi eip, MEMORYBASE
mov VMBASE, $RESULT
////////////////////
SEARCH:
find VMBASE, #0FB?542410E9#
cmp $RESULT, 00
jne found
find A_ADDRESS, #0FB?542410E9#
cmp $RESULT, 00
je SEARCH_3
////////////////////
SEARCH_2:
mov A_ADDRESS, $RESULT
gmemi A_ADDRESS, MEMORYBASE
mov VMBASE, $RESULT
mov $RESULT, A_ADDRESS
jmp found
////////////////////
SEARCH_3:
findmem  #0FB?542410E9#, CODESECTION
cmp $RESULT, 00
jne SEARCH_3_A
pause
pause
pause
////////////////////
SEARCH_3_A:
mov A_ADDRESS, $RESULT
gmemi A_ADDRESS, MEMORYBASE
mov VMBASE, $RESULT
mov $RESULT, A_ADDRESS
jmp found
pause
pause
////////////////////
found:
mov FOUND, $RESULT
add PLUS_1, FOUND
sub PLUS_1, VMBASE
mov PLUS_1, PLUS_1
log PLUS_1
bp FOUND
bphws FOUND, "x"
esto
mov ID,  [esp+10]
mov ID2, [esp+14]
alloc 1000
mov mem, $RESULT
mov baceip, eip
////////////////////
Ask3:
ask "输入可用机器码的前8个字节,如:AAAABBBB"
cmp $RESULT,0
je Ask3
cmp $RESULT, -1
je Ask3
mov ID_1, $RESULT
////////////////////
Ask4:
ask "输入可用机器码的后8个字节,如:CCCCDDDD"
cmp $RESULT,0
je Ask4
cmp $RESULT, -1
je Ask4
mov ID_2, $RESULT
mov temp2,eax
mov test, ##+"0000-0000-0000-0000"
mov [mem], test
mov eax, ID_1
shr eax, 10
mov I1, ax
mov eax, ID_1
mov I2, ax
itoa I1, 16.
mov I1, $RESULT
len I1
cmp $RESULT, 04
je CW_GO
////////////////////
AB1:
cmp $RESULT, 03
jne AB2
eval "0{I1}"
mov I1, $RESULT
jmp CW_GO
////////////////////
AB2:
cmp $RESULT, 02
jne AB3
eval "00{I1}"
mov I1, $RESULT
jmp CW_GO
////////////////////
AB3:
cmp $RESULT, 01
jne AB4
eval "000{I1}"
mov I1, $RESULT
jmp CW_GO
////////////////////
AB4:
cmp $RESULT, 00
jne AB5
mov I1, "0000"
jmp CW_GO
////////////////////
AB5:
pause
pause
pause
////////////////////
CW_GO:
itoa I2, 16.
mov I2, $RESULT
len I2
cmp $RESULT, 04
je CW_GO_2
////////////////////
AB1A:
cmp $RESULT, 03
jne AB2A
eval "0{I2}"
mov I2, $RESULT
jmp CW_GO_2
////////////////////
AB2A:
cmp $RESULT, 02
jne AB3A
eval "00{I2}"
mov I2, $RESULT
jmp CW_GO_2
////////////////////
AB3A:
cmp $RESULT, 01
jne AB4
eval "000{I2}"
mov I2, $RESULT
jmp CW_GO_2
////////////////////
AB4A:
cmp $RESULT, 00
jne AB5A
mov I2, "0000"
jmp CW_GO_2
////////////////////
AB5A:
pause
pause
pause
////////////////////
CW_GO_2:
eval "{I1}-{I2}"
mov test, ##+$RESULT
mov [mem], test
mov eax, ID_2
shr eax, 10
mov I3, ax
mov eax, ID_2
mov I4, ax
itoa I3, 16.
mov I3, $RESULT
len I3
cmp $RESULT, 04
je CW_GO_3
////////////////////
AB1B:
cmp $RESULT, 03
jne AB2B
eval "0{I3}"
mov I3, $RESULT
jmp CW_GO_3
////////////////////
AB2B:
cmp $RESULT, 02
jne AB3B
eval "00{I3}"
mov I3, $RESULT
jmp CW_GO_3
////////////////////
AB3B:
cmp $RESULT, 01
jne AB4B
eval "000{I3}"
mov I3, $RESULT
jmp CW_GO_3
////////////////////
AB4B:
cmp $RESULT, 00
jne AB5B
mov I3, "0000"
jmp CW_GO_3
////////////////////
AB5B:
pause
pause
pause
////////////////////
CW_GO_3:
itoa I4, 16.
mov I4, $RESULT
len I4
cmp $RESULT, 04
je CW_GO_4
////////////////////
AB1C:
cmp $RESULT, 03
jne AB2C
eval "0{I4}"
mov I4, $RESULT
jmp CW_GO_4
////////////////////
AB2C:
cmp $RESULT, 02
jne AB3C
eval "00{I4}"
mov I4, $RESULT
jmp CW_GO_4
////////////////////
AB3C:
cmp $RESULT, 01
jne AB4C
eval "000{I4}"
mov I4, $RESULT
jmp CW_GO_4
////////////////////
AB4C:
cmp $RESULT, 00
jne AB5C
mov I4, "0000"
jmp CW_GO_4
////////////////////
AB5C:
pause
pause
pause
////////////////////
CW_GO_4:
eval "{I3}-{I4}"
mov test, ##+$RESULT
mov [mem+0A], test
////////////////////
BIG_LOOP:
mov CALC, mem
////////////////////
BIG_LOOP_2:
cmp [mem], 61, 01
je 20
cmp [mem], 62, 01
je 20
cmp [mem], 63, 01
je 20
cmp [mem], 64, 01
je 20
cmp [mem], 65, 01
je 20
cmp [mem], 66, 01
je 20
////////////////////
BIG_LOOP_3:
inc mem
inc counta
cmp counta, 13
je FERTIG
jmp BIG_LOOP_2
////////////////////
20:
sub [mem], 20
jmp BIG_LOOP_3
////////////////////
FERTIG:
mov mem, CALC
mov counta, 00
cmp SECOND_LOOP, 01
je END_SECOND_LOOP
readstr [mem], 13
mov STRING, $RESULT
str STRING
mov STRING, STRING
mov eax, temp2
fill mem, 100, 00
mov temp2, eax
mov test, ##+"0000-0000-0000-0000"
mov [mem], test
mov eax, [esp+10]
mov I1, ax
shr eax, 10
mov I2, ax
mov eax, [esp+14]
mov I3, ax
shr eax, 10
mov I4, ax
itoa I1, 16.
mov I1, $RESULT
len I1
cmp $RESULT, 04
je CW_GO_5
////////////////////
AB1D:
cmp $RESULT, 03
jne AB2D
eval "0{I1}"
mov I1, $RESULT
jmp CW_GO_5
////////////////////
AB2D:
cmp $RESULT, 02
jne AB3D
eval "00{I1}"
mov I1, $RESULT
jmp CW_GO_5
////////////////////
AB3D:
cmp $RESULT, 01
jne AB4D
eval "000{I4}"
mov I1, $RESULT
jmp CW_GO_5
////////////////////
AB4D:
cmp $RESULT, 00
jne AB5D
mov I1, "0000"
jmp CW_GO_5
////////////////////
AB5D:
pause
pause
pause
////////////////////
CW_GO_5:
itoa I2, 16.
mov I2, $RESULT
len I2
cmp $RESULT, 04
je CW_GO_6
////////////////////
AB1E:
cmp $RESULT, 03
jne AB2E
eval "0{I2}"
mov I2, $RESULT
jmp CW_GO_6
////////////////////
AB2E:
cmp $RESULT, 02
jne AB3E
eval "00{I2}"
mov I2, $RESULT
jmp CW_GO_6
////////////////////
AB3E:
cmp $RESULT, 01
jne AB4E
eval "000{I2}"
mov I2, $RESULT
jmp CW_GO_6
////////////////////
AB4E:
cmp $RESULT, 00
jne AB5E
mov I2, "0000"
jmp CW_GO_6
////////////////////
AB5E:
pause
pause
pause
////////////////////
CW_GO_6:
eval "{I1}-{I2}"
mov test, ##+$RESULT
mov [mem], test
itoa I3, 16.
mov I3, $RESULT
len I3
cmp $RESULT, 04
je CW_GO_7
////////////////////
AB1F:
cmp $RESULT, 03
jne AB2F
eval "0{I3}"
mov I3, $RESULT
jmp CW_GO_7
////////////////////
AB2F:
cmp $RESULT, 02
jne AB3F
eval "00{I3}"
mov I3, $RESULT
jmp CW_GO_7
////////////////////
AB3F:
cmp $RESULT, 01
jne AB4F
eval "000{I3}"
mov I3, $RESULT
jmp CW_GO_7
////////////////////
AB4F:
cmp $RESULT, 00
jne AB5F
mov I3, "0000"
jmp CW_GO_7
////////////////////
AB5F:
pause
pause
pause
////////////////////
CW_GO_7:
itoa I4, 16.
mov I4, $RESULT
len I4
cmp $RESULT, 04
je CW_GO_8
////////////////////
AB1G:
cmp $RESULT, 03
jne AB2G
eval "0{I4}"
mov I4, $RESULT
jmp CW_GO_8
////////////////////
AB2G:
cmp $RESULT, 02
jne AB3G
eval "00{I4}"
mov I4, $RESULT
jmp CW_GO_8
////////////////////
AB3G:
cmp $RESULT, 01
jne AB4G
eval "000{I4}"
mov I4, $RESULT
jmp CW_GO_8
////////////////////
AB4G:
cmp $RESULT, 00
jne AB5G
mov I4, "0000"
jmp CW_GO_8
////////////////////
AB5G:
pause
pause
pause
////////////////////
CW_GO_8:
eval "{I3}-{I4}"
mov test, ##+$RESULT
mov [mem+0A], test
mov SECOND_LOOP, 01
jmp BIG_LOOP
////////////////////
END_SECOND_LOOP:
readstr [mem], 13
mov STRING_2, $RESULT
str STRING_2
mov STRING_2, STRING_2
mov eax, temp2
fill mem, 100, 00
mov SECOND_LOOP, 00
mov [mem], ID_1
mov [mem+04], ID_2
mov [mem+12], [mem], 2
mov [mem+10], [mem+2], 2
mov [mem+16], [mem+4], 2
mov [mem+14], [mem+6], 2
mov ID_1, [mem+10] 
mov ID_2,[mem+14] 
fill mem, 100, 00
bc FOUND
bphwc
readstr [eip], 0A
mov place, $RESULT
buf place
mov test,eip
add test, 05
gci test, DESTINATION
mov ort, $RESULT
eval "jmp {mem}"
asm eip, $RESULT

mov [mem], #81FAAAAAAAAA751A81F9AAAAAAAA7512BABBBBBBBBB9CCCCCCCC89542410894C24149090#
cmp $RESULT, 01
jmp END_SECOND_LOOP_2
////////////////////
END_SECOND_LOOP_2:
add mem, 22
mov [mem], place
sub mem, 22
mov [mem+02],ID
mov [mem+0A],ID2
mov [mem+11],ID_1
mov [mem+16],ID_2
eval "jmp {ort}"
asm mem+27, $RESULT
add PLUS_2, ort
sub PLUS_2, VMBASE
mov PLUS_2, PLUS_2

readstr [mem], 028


jmp FULL_END
esto
pause
pause
////////////////////
VARSINIT:
/////////////////ZENGHW ADD ////////
var tempdata 

var vmaddr
var apiaddr
var IAT_Start
var IAT_End
var vmapiaddr

var EipForOep_1
var EipForOep_2
var EipForOep_3
var oep
var bpforoep
var tmp1
var tmp2
var EXTRA_2
var EXTRA
var mem

var SECOND_LOOP
var STRING_2
var counta
var test
var STRING
var CALC
var I1
var I2
var I3
var I4
var PLUS_1
var PLUS_2
var CHECK
var TEMP_CHECK
var CODESECTION
var CODESECTION_SIZE
var dll
var call

////////////////////
gpa "DeviceIoControl", "kernel32.dll"
mov DeviceIoControl,    $RESULT
gpa "VirtualAlloc",    "kernel32.dll"
mov VirtualAlloc,       $RESULT
gpa "VirtualProtect",  "kernel32.dll"
mov VirtualProtect,     $RESULT
gpa "MapViewOfFile",    "kernel32.dll"
mov MapViewOfFile,      $RESULT

ret
////////////////////
FULL_END:
cmp TEMP_CHECK, 0
je FULL_END_2
free TEMP_CHECK
////////////////////
FULL_END_2:

//pause
//ret
//start:
findoep:
BPHWCALL
BPHWS bpforoep, "r"
run

mov EipForOep_2, eip
mov EipForOep_2, [EipForOep_2]
and EipForOep_2, 0ff
cmp EipForOep_2, E8
je findoep2

sto
sto
mov oep, eip
pause  //此处暂停后,可先查看IAT START和IAT END,然后修改fixiat里面的对应内容
msg "此处暂停后,可先查看IAT的起始和终止地址,然后修改fixiat里面对应的IAT_Start和IAT_Start!"
jmp fixiat

findoep2:
//msg "修复后,请手动查找OEP!"
sti
sto
sto
sto
sto
sto
mov oep, eip

fixiat:
mov IAT_Start, 0040306C  ////////////////////////////////////////
mov IAT_End, 00403098  ////////////////////////////////////////

fix:
mov eip, [IAT_Start]

mov EipForOep_3, eip
mov EipForOep_3, [EipForOep_3]
and EipForOep_3, 0ff
cmp EipForOep_3, 68
jne skipfix2

sto
sto
sto
sto
sto
sti

mov tmp1, eip
find eip, #7C#
cmp $RESULT, 0
je F2
mov tmp2, $RESULT
mov [tmp2], #EB#
mov eip, tmp1

F2:
run
sto

cmp eip, 07000000
ja fix2

mov vmapiaddr, eip
sub vmapiaddr, vmaddr
add vmapiaddr, kernel32base
mov [IAT_Start], vmapiaddr
add IAT_Start,4
cmp IAT_Start, IAT_End
ja end
cmp [IAT_Start], 0
je skipfix
jmp fix

fix2:
mov eip, [IAT_Start]

mov EipForOep_3, eip
mov EipForOep_3, [EipForOep_3]
and EipForOep_3, 0ff
cmp EipForOep_3, 68
jne skipfix2

sto
sto
sto
sto
sto
sti

mov tmp1, eip
find eip, #7C#
cmp $RESULT, 0
je F3
mov tmp2, $RESULT
mov [tmp2], #EB#
mov eip, tmp1

F3:
run
sto
mov apiaddr, eip
mov [IAT_Start], apiaddr
add IAT_Start,4
cmp IAT_Start, IAT_End
ja end
cmp [IAT_Start], 0
je skipfix
jmp fix

skipfix:
add IAT_Start,4
cmp [IAT_Start], 0
je skipfix
jmp fix

skipfix2:
add IAT_Start,4
cmp IAT_Start, IAT_End
ja end
jmp fix

error:
msg "Fix IAT wrong!"
ret

end:
BPHWCALL
mov eip, oep
AN eip
ret

 


文章标题:Zprotect1.4-1.6patchKEY脱壳
文章位置:http://hbruida.cn/article/jhihic.html