首页
社区
课程
招聘
[原创]看雪CTF2017第8题
2017-6-16 01:41 3837

[原创]看雪CTF2017第8题

2017-6-16 01:41
3837

1. TlsCallback

创建了6个线程, 前3个线程是负责smc解码的, 后3个线程没用 

.text:00402D30 TlsCallback_2


线程1: 解码004025DC处的跳转及check1函数

.text:00402830 thread1

.text:004025DC                 push    offset loc_4025E2
.text:004025E1                 retn
.text:004025E2                 lea     ecx, [ebp+var_110]
.text:004025E8                 push    ecx
.text:004025E9                 call    check1


线程2: 解码0040263C处的跳转及check2函数

.text:00402970 thread2

.text:0040263C                 push    offset loc_402642
.text:00402641                 retn
.text:00402642                 lea     eax, [ebp+var_110]
.text:00402648                 push    eax
.text:00402649                 call    check2


线程3: 解码0040269C处的跳转及check3函数

.text:00402A90 thread3

.text:0040269C                 push    offset loc_4026A2
.text:004026A1                 retn
.text:004026A2                 lea     edx, [ebp+var_110]
.text:004026A8                 push    edx
.text:004026A9                 call    check3


2. 主流程

一个自定义的虚拟机


校验函数

.text:00402700 fn_check


检测代码改动

.text:00402481                 call    check_text_areas


sn=base64_decode(sn)

.text:0040251D                 call    base64_decode


sn的格式(共90位): (20位)--(39位)--(27位)

.text:00402573                 cmp     [ebp+var_130], 90
.text:0040257A                 jnz     short loc_4025AC
.text:0040257C                 movsx   edx, [ebp+Dst+14h]
.text:00402583                 cmp     edx, '-'
.text:00402586                 jnz     short loc_4025AC
.text:00402588                 movsx   eax, [ebp+Dst+15h]
.text:0040258F                 cmp     eax, '-'
.text:00402592                 jnz     short loc_4025AC
.text:00402594                 movsx   ecx, [ebp+Dst+3Dh]
.text:0040259B                 cmp     ecx, '-'
.text:0040259E                 jnz     short loc_4025AC
.text:004025A0                 movsx   edx, [ebp+Dst+3Eh]
.text:004025A7                 cmp     edx, '-'
.text:004025AA                 jz      short loc_4025B2


校验前20位

(sn1 xor abcdefg...) * 98765432109876543210123 == 1549780652036258484424751705102781884386113

.text:004025E9                 call    check1


校验中间39位

(sn2 xor abcdefg...) ^ 2 == 13095069099216326605010245808779535277211541324456558063162414338128147458401

.text:00402649                 call    check2


检验后27位, sn3视为16进制

sn3 ^ 15691529100101820131 mod 114433688655117320765854989491151409201 == 71639176673360967005214790689576394595

.text:004026A9                 call    check3


sn3作为16进制转换的时候是有符号转换的, 所以导致>=80的值无法正常转换

这里只需要关心能产生0x00的值即可(有挺多个, 如0x89) 

	for (int i = 8; i < 16; i++)
	{
		for (int k = 0; k < 16; k++)
		{
			int v = (char)((i << 4) | k);
			char v1 = v / 16;
			char v2 = v % 16;
			v1 += v1 < 0 ? 0x37 : 0x30;
			v2 += v2 < 0 ? 0x37 : 0x30;
			// 这里非数字字母的字符, 后面都会被0替代
			printf("%02X: %c%c\n", (BYTE)v, v1, v2);
		}
	}


3. 后27位计算


已知:

e = 15691529100101820131

n = 114433688655117320765854989491151409201

m = 71639176673360967005214790689576394595


分解得到

d = 98395538376216701876091105738065053007


c = m ^ d mod n = 55986991232018409201158808992848352475 (2A1EB3C9579DFA307CF5B6C8730114DB) 


c中>=0x80的是无法通过转换得到的(如B3, C9, ...)


sn3(27字节) > c (16字节)

c ^ e mod n = m, 根据(a * b) mod n = (a mod n) * (b mod n) mod n

得 (c mod n) * (c mod n) * ... mod n = m

再由c mod n = (c + k * n) mod n, 代入上式得到

(c + k * n) ^ e mod n = m


根据下面这两个条件可以立刻得到很多解(如: 0208674855670d0560353c3a1d3e242e217766)

sn3 = c + k * n

sn3中的字节必须小于0x80


得到的解, 在前面填充可以转换成00的值:  89898989898989890208674855670d0560353c3a1d3e242e217766

与前面的串连接起来base64得到最终结果 

UFdVXVRTVVFYWltdXV9XQkFDQEUtLVBTV1BWVVFQUVxeWVxfWENDQkRCQE5CTEBCWFZaVVRTVlxZU1lcXC0tiYmJiYmJiYkCCGdIVWcNBWA1PDodPiQuIXdm


4. 穷举脚本

import itertools
n=114433688655117320765854989491151409201
e=15691529100101820131
c=55986991232018409201158808992848352475
def valid_result(v):
    sv=hex(v)[2:]
    sv_len=len(sv)
    if (sv_len&1) != 0:
        sv='0'+sv
        sv_len=sv_len+1
    for i in itertools.count(0,2):
        if (i>=sv_len):
            break
        if (ord(sv[i])>=0x38):
            return False
    return True
def solve(ibegin,iend):
    g=0
    nc=c
    k=0
    for i in itertools.count(0):
        g=g+1
        nc=nc+n
        if ((ibegin+i)>=iend):
            break;
        #print(nc)
        #print(pow(nc,e,n))
        if (g>=1000000):
            print(ibegin+i)
            g=0        
        if (valid_result(nc)):
            print('---')
            print(i)
            print(nc)
            print(hex(nc))
            #break
    return
solve(0,4294967296)
'''
---
396154
45333533916159234226406484520676079360374630
0x208674855670d0560353c3a1d3e242e217766
---
456935
52288927946305920099875916636937753163020611
0x2583f59392b7266031a47246a1e672b013943
...
'''



[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
点赞1
打赏
分享
最新回复 (1)
雪    币: 19
活跃值: (128)
能力值: ( LV9,RANK:146 )
在线值:
发帖
回帖
粉丝
wendax 2018-6-9 01:44
2
0
这么晚了,偷偷吃点翔,不会被发现吧
游客
登录 | 注册 方可回帖
返回