-
-
看雪CTF 2019总决赛 第六题 三道八佛 IDA脱壳脚本
-
发表于: 2020-1-2 17:25 5861
-
发现很多都用X32Debug/X64Debug进行脱壳,发一个IDA脱壳的脚本。
脚本主要功能是查找SMC和代码拷贝执行的特征:
1)从当前EIP开始查找SMC代码和拷贝执行代码
2)如果发现SMC代码,没发现拷贝执行代码,则让程序运行到SMC代码结束位置,继续到1)循环
3)如果发现拷贝代码,没发现SMC代码,则将拷贝代码全部NOP,并让程序执行到拷贝结束位置,继续到1)循环
4)如果既发现SMC代码也发现拷贝代码,将让程序运行到地址小的位置,继续循环
5)发现0x4EED14位置存在SEH反调试,单独处理下即可。
脚本使用方法:
1)首先手动在start函数入口设置断点,并让IDA断在start入口,执行一下脚本
2)输入用户名和密码
3)此时程序会断在0x4013F7位置,再次执行脚本,脚本运行5分钟左右断在0x4FB939,后面就是解密后的算法。
虽然程序在代码拷贝后会清除前面的代码,但是清除的位置都是在0x508000开始的段中,而我们的代码在0x401000-0x506000范围,因此不会影响。但是如果不管它,清除会越界。由于每次清除都是以EDI值开始,因此在每次NOP掉拷贝代码后将EDI设置成0x508000即可。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298import
struct
from idaapi import *
from idc import *
from idautils import *
def addBptByAddr(addr):
AddBpt(addr)
SetBptAttr(addr, BPTATTR_FLAGS, BPT_ENABLED | BPT_BRK)
def FindDataFromRange(segStart, segEnd, target):
ea = segStart
while
ea < segEnd:
readLen = 1024
if
(ea + readLen) >= segEnd:
readLen = segEnd - ea
rawdex1 = idaapi.dbg_read_memory(ea, readLen)
if
rawdex1 == None:
return
0
a = rawdex1.find(target)
if
a>= 0:
return
ea + a
if
readLen == 1024:
ea = ea + 512
else
:
ea = ea + readLen
return
0
def findXXX(startEA, endEA):
ea = startEA
while
ea < endEA:
#print (str(hex(ea)))
#addr = find_binary(ea, SEARCH_DOWN | SEARCH_NEXT,
'E8 00 00 00 00 59 81'
, radix=16)
addr = FindDataFromRange(ea, ea + 0x400,
'\xE8\x00\x00\x00\x00\x59\x81'
)
if
addr == 0:
return
0
if
idc.Dword(addr + 0x24) == 0xB9310F51:
return
addr
ea = addr + 1
return
0
def bypassCopy(pcValue):
#pcValue=GetRegValue(
'eip'
)
'bypassCopy start Addr = '
+ (str(hex(pcValue)))
ea = findXXX(pcValue, pcValue+0x1000)
copyStartCode = ea
'copyStartCode = '
+ (str(hex(ea)))
if
ea > 0:
if
copyStartCode - pcValue > 0x200:
'copyStartCode size more 0x200 ....fail'
return
0, 0
ea = FindDataFromRange(ea, ea + 0x400,
'\x9D\x61\x5F\xFF\xD0'
)
if
ea > 0:
patch_bytes(copyStartCode,
'\x90'
* (ea + 6 - copyStartCode))
refresh_debugger_memory()
pachCodeSize = ea + 6 - copyStartCode;
'pach code endAddr = '
+ (str(hex(ea+6)))
'pach code size = '
+ (str(hex(pachCodeSize)))
MakeCode(ea+6)
#AddBpt(ea+6)
#SetBptAttr(ea+6, BPTATTR_FLAGS, BPT_ENABLED | BPT_BRK)
'bypassCopy success1'
return
ea+6, copyStartCode
ea = FindDataFromRange(copyStartCode, copyStartCode + 0x400,
'\x9D\x61\x5F\xE8\x01\x00\x00'
)
if
ea > 0:
pachCodeEndAddr = copyStartCode + 5 + idc.Dword(copyStartCode + 0x0e) - idc.Dword(copyStartCode + 0x08)
pachCodeSize = pachCodeEndAddr - copyStartCode;
patch_bytes(copyStartCode,
'\x90'
* pachCodeSize)
refresh_debugger_memory()
'pach code endAddr = '
+ (str(hex(pachCodeEndAddr)))
'pach code size = '
+ (str(hex(pachCodeSize)))
'bypassCopy success2'
return
pachCodeEndAddr, copyStartCode
'find copy fail1'
return
0, 0
'find copy fail0'
return
0, 0
def findSMC(pcValue):
'findSMC1 startAddr = '
+ (str(hex(pcValue)))
ea = pcValue
smcStartAddr = 0
curEa1 = ea
while
curEa1 < pcValue + 0x400:
curEa = FindDataFromRange(curEa1, pcValue + 0x400,
'\xE8\x00\x00\x00\x00\x5E\x81\xEE'
)
if
curEa != 0 and idc.Word(curEa + 0x0C) == 0xC681 and idc.Byte(curEa + 0x12) == 0xB9 and idc.Byte(curEa + 0x17) == 0xFC:
smcStartAddr = curEa
break
;
elif curEa != 0 and idc.Word(curEa + 0x0C) == 0xC681 and idc.Byte(curEa + 0x12) == 0xB9 and idc.Byte(curEa + 0x17) == 0xEB:
offset = idc.Byte(curEa + 0x18)
'offset1 = '
+ (str(hex(offset)))
tempAddr = curEa + 0x17 + 2 + offset
'tempAddr = '
+ (str(hex(tempAddr)))
if
idc.Byte(tempAddr) == 0xFC or idc.Byte(tempAddr + 3) == 0xFC:
smcStartAddr = curEa
break
elif curEa != 0 and idc.Word(curEa + 0x0C) == 0xC681 and idc.Word(curEa + 0x12) == 0x2EB and idc.Byte(curEa + 0x16) == 0xB9 and idc.Byte(curEa + 0x1B) == 0xFC:
smcStartAddr = curEa
break
elif curEa != 0 and idc.Word(curEa + 0x0C) == 0xC681 and idc.Word(curEa + 0x12) == 0x2EB and idc.Byte(curEa + 0x16) == 0xB9 and idc.Byte(curEa + 0x1E) == 0xFC:
smcStartAddr = curEa
break
elif curEa != 0 and idc.Word(curEa + 0x0C) == 0xC681 and idc.Word(curEa + 0x12) == 0x2EB and idc.Byte(curEa + 0x16) == 0xB9 and idc.Byte(curEa + 0x22) == 0xFC:
smcStartAddr = curEa
break
elif curEa != 0 and idc.Word(curEa + 0x0C) == 0xC681 and idc.Byte(curEa + 0x12) == 0xB9 and idc.Word(curEa + 0x17) == 0x2EB and idc.Byte(curEa + 0x1B) == 0xFC:
smcStartAddr = curEa
elif curEa != 0 and idc.Word(curEa + 0x0C) == 0xC681 and idc.Byte(curEa + 0x12) == 0xB9 and idc.Word( curEa + 0x17) == 0x2EB and idc.Byte(curEa + 0x1E) == 0xFC:
smcStartAddr = curEa
break
elif curEa != 0 and idc.Word(curEa + 0x0C) == 0xC681 and idc.Byte(curEa + 0x12) == 0xB9 and idc.Word(curEa + 0x1A) == 0x2EB and idc.Byte(curEa + 0x1E) == 0xFC:
smcStartAddr = curEa
break
elif curEa != 0 and idc.Word(curEa + 0x0C) == 0xC681 and idc.Byte(curEa + 0x12) == 0xEB:
offset = idc.Byte(curEa + 0x13)
'offset2 = '
+ (str(hex(offset)))
tempAddr = curEa + 0x13 + 1 + offset
'tempAddr = '
+ (str(hex(tempAddr)))
if
idc.Byte(tempAddr) == 0xB9 and idc.Byte(tempAddr + 0x05) == 0xFC:
smcStartAddr = curEa
break
if
idc.Byte(tempAddr) == 0xB9 and idc.Byte(tempAddr + 0x0C) == 0xFC:
smcStartAddr = curEa
break
if
curEa != 0:
curEa1 = curEa + 1
continue
curEa1 = curEa1 + 1
'smcStartAddr = '
+ (str(hex(smcStartAddr)))
esiAddr = FindDataFromRange(pcValue, pcValue + 0x400,
'\x88\x46\xFF'
)
if
0 == esiAddr:
'find smc false, esiAddr is 0'
return
0, 0
'esiAddr = '
+ (str(hex(esiAddr)))
ea = FindDataFromRange(pcValue, pcValue + 0x400,
'\x85\xc9'
)
if
ea > 0 and idc.Byte(ea + 0x02) == 0x75:
'findSMC1 endAddr = '
+ (str(hex(ea + 4)))
if
ea - esiAddr > 0x100:
'find smc10 success: esiAddr'
return
esiAddr + 3, smcStartAddr
'find smc1 success'
return
ea + 4, smcStartAddr
elif ea > 0 and idc.Word(ea + 0x02) == 0x850F:
'findSMC1 endAddr = '
+ (str(hex(ea + 8)))
if
ea - esiAddr > 0x100:
'find smc20 success: esiAddr'
return
esiAddr + 3, smcStartAddr
'find smc2 success'
return
ea + 8, smcStartAddr
elif ea != 0 and idc.Word(ea + 0x02) == 0x2EB and idc.Byte(ea + 0x06) == 0x75:
'findSMC1 endAddr = '
+ (str(hex(ea + 8)))
if
ea - esiAddr > 0x100:
'find smc30 success: esiAddr'
return
esiAddr + 3, smcStartAddr
'find smc3 success'
return
ea + 8, smcStartAddr
elif ea != 0 and idc.Word(ea + 0x02) == 0x2EB and idc.Word(ea + 0x06) == 0x850F:
'findSMC1 endAddr = '
+ (str(hex(ea + 12)))
if
ea - esiAddr > 0x100:
'find smc40 success: esiAddr'
return
esiAddr + 3, smcStartAddr
'find smc4 success'
return
ea + 12, smcStartAddr
'find smc false'
return
0, 0
if
not
'setflag'
in dir():
'set breakpoint'
patch_bytes(0x4013F7,
'\xE9\x41\x02\x00\x00'
)
addBptByAddr(0x4013F7)
cnt = 3124 #4FB939
pcValue=GetRegValue(
'eip'
)
i = 0
while
i < cnt:
'=============================================i = '
+ str(i)
if
pcValue == 0x4FB939:
break
if
pcValue == 0x4eed14:
'****** SEH anti debug ************'
patch_bytes(pcValue,
'\x90'
* 0x1cc)
refresh_debugger_memory()
pcValue = 0x4EEEE0
run_to(pcValue)
GetDebuggerEvent(WFNE_SUSP, -1)
i = i + 1
continue
if
pcValue == 0x46589D:
'******pcValue = 0x46589D handle************'
pcValue = 0x4658D5
run_to(pcValue)
GetDebuggerEvent(WFNE_SUSP, -1)
i = i + 1
continue
if
pcValue == 0x465FC5:
'******pcValue = 0x465FC5 handle************'
pcValue = 0x466001
run_to(pcValue)
GetDebuggerEvent(WFNE_SUSP, -1)
i = i + 1
continue
if
pcValue == 0x466208:
'******pcValue = 0x466208 handle************'
pcValue = 0x46623C
run_to(pcValue)
GetDebuggerEvent(WFNE_SUSP, -1)
i = i + 1
continue
if
pcValue == 0x4689EC:
'******pcValue = 0x4689EC handle************'
pcValue = 0x468A24
run_to(pcValue)
GetDebuggerEvent(WFNE_SUSP, -1)
i = i + 1
continue
if
pcValue == 0x46C118: #1345
'******pcValue = 0x46C118 handle************'
pcValue = 0x46C14C
run_to(pcValue)
GetDebuggerEvent(WFNE_SUSP, -1)
i = i + 1
continue
if
pcValue == 0x46D82F: #1364
'******pcValue = 0x46D82F handle************'
pcValue = 0x46D85F
run_to(pcValue)
GetDebuggerEvent(WFNE_SUSP, -1)
i = i + 1
continue
if
pcValue == 0x46DBD4: #1366
'******pcValue = 0x46DBD4 handle************'
pcValue = 0x46DC0C
run_to(pcValue)
GetDebuggerEvent(WFNE_SUSP, -1)
i = i + 1
continue
if
pcValue == 0x4A5B3D: #1366
'******pcValue = 0x4A5B3D handle************'
pcValue = 0x4A5B69
run_to(pcValue)
GetDebuggerEvent(WFNE_SUSP, -1)
i = i + 1
continue
if
pcValue == 0x4ADA7A: #2164
'******pcValue = 0x4ADA7A handle************'
pcValue = 0x4ADAA6
run_to(pcValue)
GetDebuggerEvent(WFNE_SUSP, -1)
i = i + 1
continue
if
pcValue == 0x4B78FF: #2164
'******pcValue = 0x4B78FF handle************'
pcValue = 0x4B7927
run_to(pcValue)
GetDebuggerEvent(WFNE_SUSP, -1)
i = i + 1
continue
'******findSMC start************'
smcValue, smcStartAddr = findSMC(pcValue)
'******findSMC end and bypassCopy start ************'
copyValue ,copyStartAddr= bypassCopy(pcValue)
'******bypassCopy end************'
'smcValue = '
+ (str(hex(smcValue))) +
', smcStartAddr = '
+ (str(hex(smcStartAddr)))
'copyValue = '
+ (str(hex(copyValue))) +
', copyStartAddr = '
+ (str(hex(copyStartAddr)))
if
(smcValue==0 and copyValue == 0) or (smcValue >= 0x506000 or copyValue >= 0x506000) :
'******error************'
'smcStartAddr = '
+ (str(hex(smcStartAddr)))
'smcValue = '
+ (str(hex(smcValue)))
'copyStartAddr = '
+ (str(hex(copyStartAddr)))
'copyValue = '
+ (str(hex(copyValue)))
break
if
smcValue > 0 and smcStartAddr == 0:
'******smcStartAddr error************'
'smcStartAddr = '
+ (str(hex(smcStartAddr)))
'smcValue = '
+ (str(hex(smcValue)))
break
if
copyValue > 0 and copyStartAddr == 0:
'******copyStartAddr error************'
'copyStartAddr = '
+ (str(hex(copyStartAddr)))
'copyValue = '
+ (str(hex(copyValue)))
break
if
(copyValue == 0) or ((smcStartAddr > 0) and (smcStartAddr < copyStartAddr)):
'******findSMC run_to start ************'
pcValue = smcValue
run_to(pcValue)
GetDebuggerEvent(WFNE_SUSP, -1)
'******findSMC run_to end ************'
else
:
'******bypassCopy run_to start ************'
pcValue = copyValue
run_to(pcValue)
GetDebuggerEvent(WFNE_SUSP, -1)
SetRegValue(0x508000,
'edi'
)
'******bypassCopy run_to end ************'
i = i + 1
赞赏
他的文章
- 看雪CTF 2019总决赛 第六题 三道八佛 IDA脱壳脚本 5862
- [原创]看雪CTF2019Q3第四题WP 6129
- [原创]看雪CTF2019Q3 第二题WP 7033
- [2019看雪CTF晋级赛Q3第九题WP 12771
- [原创]看雪CTF2019晋级赛Q2第三题 5194
赞赏
雪币:
留言: