-
-
看雪CTF 2019总决赛 第六题 三道八佛 IDA脱壳脚本
-
发表于: 2020-1-2 17:25 5668
-
发现很多都用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即可。
import 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') print 'bypassCopy start Addr = ' + (str(hex(pcValue))) ea = findXXX(pcValue, pcValue+0x1000) copyStartCode = ea print 'copyStartCode = ' + (str(hex(ea))) if ea > 0: if copyStartCode - pcValue > 0x200: print '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; print 'pach code endAddr = ' + (str(hex(ea+6))) print 'pach code size = ' + (str(hex(pachCodeSize))) MakeCode(ea+6) #AddBpt(ea+6) #SetBptAttr(ea+6, BPTATTR_FLAGS, BPT_ENABLED | BPT_BRK) print '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() print 'pach code endAddr = ' + (str(hex(pachCodeEndAddr))) print 'pach code size = ' + (str(hex(pachCodeSize))) print 'bypassCopy success2' return pachCodeEndAddr, copyStartCode print 'find copy fail1' return 0, 0 print 'find copy fail0' return 0, 0 def findSMC(pcValue): print '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) print 'offset1 = ' + (str(hex(offset))) tempAddr = curEa + 0x17 + 2 + offset print '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) print 'offset2 = ' + (str(hex(offset))) tempAddr = curEa + 0x13 + 1 + offset print '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 print 'smcStartAddr = ' + (str(hex(smcStartAddr))) esiAddr = FindDataFromRange(pcValue, pcValue + 0x400, '\x88\x46\xFF') if 0 == esiAddr: print 'find smc false, esiAddr is 0' return 0, 0 print 'esiAddr = ' + (str(hex(esiAddr))) ea = FindDataFromRange(pcValue, pcValue + 0x400, '\x85\xc9') if ea > 0 and idc.Byte(ea + 0x02) == 0x75: print 'findSMC1 endAddr = ' + (str(hex(ea + 4))) if ea - esiAddr > 0x100: print 'find smc10 success: esiAddr' return esiAddr + 3, smcStartAddr print 'find smc1 success' return ea + 4, smcStartAddr elif ea > 0 and idc.Word(ea + 0x02) == 0x850F: print 'findSMC1 endAddr = ' + (str(hex(ea + 8))) if ea - esiAddr > 0x100: print 'find smc20 success: esiAddr' return esiAddr + 3, smcStartAddr print 'find smc2 success' return ea + 8, smcStartAddr elif ea != 0 and idc.Word(ea + 0x02) == 0x2EB and idc.Byte(ea + 0x06) == 0x75: print 'findSMC1 endAddr = ' + (str(hex(ea + 8))) if ea - esiAddr > 0x100: print 'find smc30 success: esiAddr' return esiAddr + 3, smcStartAddr print 'find smc3 success' return ea + 8, smcStartAddr elif ea != 0 and idc.Word(ea + 0x02) == 0x2EB and idc.Word(ea + 0x06) == 0x850F: print 'findSMC1 endAddr = ' + (str(hex(ea + 12))) if ea - esiAddr > 0x100: print 'find smc40 success: esiAddr' return esiAddr + 3, smcStartAddr print 'find smc4 success' return ea + 12, smcStartAddr print 'find smc false' return 0, 0 if not 'setflag' in dir(): print 'set breakpoint' patch_bytes(0x4013F7, '\xE9\x41\x02\x00\x00') addBptByAddr(0x4013F7) cnt = 3124 #4FB939 pcValue=GetRegValue('eip') i = 0 while i < cnt: print '=============================================i = ' + str(i) if pcValue == 0x4FB939: break if pcValue == 0x4eed14: print '****** 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: print '******pcValue = 0x46589D handle************' pcValue = 0x4658D5 run_to(pcValue) GetDebuggerEvent(WFNE_SUSP, -1) i = i + 1 continue if pcValue == 0x465FC5: print '******pcValue = 0x465FC5 handle************' pcValue = 0x466001 run_to(pcValue) GetDebuggerEvent(WFNE_SUSP, -1) i = i + 1 continue if pcValue == 0x466208: print '******pcValue = 0x466208 handle************' pcValue = 0x46623C run_to(pcValue) GetDebuggerEvent(WFNE_SUSP, -1) i = i + 1 continue if pcValue == 0x4689EC: print '******pcValue = 0x4689EC handle************' pcValue = 0x468A24 run_to(pcValue) GetDebuggerEvent(WFNE_SUSP, -1) i = i + 1 continue if pcValue == 0x46C118: #1345 print '******pcValue = 0x46C118 handle************' pcValue = 0x46C14C run_to(pcValue) GetDebuggerEvent(WFNE_SUSP, -1) i = i + 1 continue if pcValue == 0x46D82F: #1364 print '******pcValue = 0x46D82F handle************' pcValue = 0x46D85F run_to(pcValue) GetDebuggerEvent(WFNE_SUSP, -1) i = i + 1 continue if pcValue == 0x46DBD4: #1366 print '******pcValue = 0x46DBD4 handle************' pcValue = 0x46DC0C run_to(pcValue) GetDebuggerEvent(WFNE_SUSP, -1) i = i + 1 continue if pcValue == 0x4A5B3D: #1366 print '******pcValue = 0x4A5B3D handle************' pcValue = 0x4A5B69 run_to(pcValue) GetDebuggerEvent(WFNE_SUSP, -1) i = i + 1 continue if pcValue == 0x4ADA7A: #2164 print '******pcValue = 0x4ADA7A handle************' pcValue = 0x4ADAA6 run_to(pcValue) GetDebuggerEvent(WFNE_SUSP, -1) i = i + 1 continue if pcValue == 0x4B78FF: #2164 print '******pcValue = 0x4B78FF handle************' pcValue = 0x4B7927 run_to(pcValue) GetDebuggerEvent(WFNE_SUSP, -1) i = i + 1 continue print '******findSMC start************' smcValue, smcStartAddr = findSMC(pcValue) print '******findSMC end and bypassCopy start ************' copyValue ,copyStartAddr= bypassCopy(pcValue) print '******bypassCopy end************' print 'smcValue = ' + (str(hex(smcValue))) + ', smcStartAddr = ' + (str(hex(smcStartAddr))) print 'copyValue = ' + (str(hex(copyValue))) + ', copyStartAddr = ' + (str(hex(copyStartAddr))) if (smcValue==0 and copyValue == 0) or (smcValue >= 0x506000 or copyValue >= 0x506000) : print '******error************' print 'smcStartAddr = ' + (str(hex(smcStartAddr))) print 'smcValue = ' + (str(hex(smcValue))) print 'copyStartAddr = ' + (str(hex(copyStartAddr))) print 'copyValue = ' + (str(hex(copyValue))) break if smcValue > 0 and smcStartAddr == 0: print '******smcStartAddr error************' print 'smcStartAddr = ' + (str(hex(smcStartAddr))) print 'smcValue = ' + (str(hex(smcValue))) break if copyValue > 0 and copyStartAddr == 0: print '******copyStartAddr error************' print 'copyStartAddr = ' + (str(hex(copyStartAddr))) print 'copyValue = ' + (str(hex(copyValue))) break if (copyValue == 0) or ((smcStartAddr > 0) and (smcStartAddr < copyStartAddr)): print '******findSMC run_to start ************' pcValue = smcValue run_to(pcValue) GetDebuggerEvent(WFNE_SUSP, -1) print '******findSMC run_to end ************' else: print '******bypassCopy run_to start ************' pcValue = copyValue run_to(pcValue) GetDebuggerEvent(WFNE_SUSP, -1) SetRegValue(0x508000, 'edi') print '******bypassCopy run_to end ************' i = i + 1
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
- 看雪CTF 2019总决赛 第六题 三道八佛 IDA脱壳脚本 5669
- [原创]看雪CTF2019Q3第四题WP 5934
- [原创]看雪CTF2019Q3 第二题WP 6760
- [2019看雪CTF晋级赛Q3第九题WP 12490
- [原创]看雪CTF2019晋级赛Q2第三题 5022
看原图
赞赏
雪币:
留言: