首页
社区
课程
招聘
看雪CTF 2019总决赛 第六题 三道八佛 IDA脱壳脚本
发表于: 2020-1-2 17:25 5861

看雪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即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
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



[注意]看雪招聘,专注安全领域的专业人才平台!

收藏
免费
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册