-
-
[原创]看雪CTF2016 1~4题 分析
-
发表于: 2016-11-9 15:12 5139
-
第一题:
进过分析程序通过sendmessage的形式来传递验证结果,其中1035为验证成功时的消息值。
找到发送消息的位置
再对沿途进行分析找到两个验证的关键点:
判断第3-6字符是否为15PB
其余都为数字,且第1,2字符相加值为0x63,最后一位为第2位+6
最后得出注册码为:1215PB8
第二题
首先分析发现与lua相关,提取运行时解密的疑似luac格式数据,
经过比较确信为lua5.3的编译格式,只是单单改了头部的标志。
发现验证使用了fnGetRegSnToVerify、fnCalcUserInputRegSnAfterEnc两个函数。而这两个函数在程序初始化时注册过,为lua调用c的典型。
经过分析,验证过程是加密后的注册码与两个固定字符串亦或后的值是否为fnGetRegSnToVerify获得的值,3个字符串都是定值:
将加密后的注册码值导入解密函数41b422,运行可得注册码:
第三题:
进过分析,程序进行了混淆。基本的混淆结构为:
push xxx
push ...
sub esp,xx
call toRet
toRet:
push retaddr
ret xx
经过初略统计大致有2、3十个混淆点,感觉不多,就采用了手动去混淆。去混淆后就能进行ida分析了。
算法分两部分:
AES和RSA,RSA部分n为32位整数,很容易分解。
具体解密脚本如下:
第4题:
搞了半天虚拟机部分最后发现关系不大
1.虚拟机
程序采用了和vmp十分相似的虚拟机,以下是手工分析的handler类型:
与vmp相比少了不少指令,执行的指令流也没进过任何的混淆,对efl的读取也是直接通过pushfd。并且使用nand来作为逻辑运算单位。主要的混淆位置是在执行vm_code时通过大量的vm_push和vm_pop。
2.算法
分析后发现是走一个简单的迷宫,迷宫由两部分异或加密:
解密后=>
30为墙,58为出口,43为入口。
每两bit为一个操作:
==>
由此可求得一串操作码。
注册码长30字符分为两部分,先获取前7个字符的MD5值,将MD5值扩展到23位。
c为一串常量
op是操作码
最终转换的验证为:
MD5_23(key[:7])^c^key[7:]==op
因为程序未设定其他任何条件,所以此处需要枚举前7为,能使后23为的值为可见字符串,具体全流程的脚本如下:
进过分析程序通过sendmessage的形式来传递验证结果,其中1035为验证成功时的消息值。
找到发送消息的位置
jz short loc_401A3B .text:00401A32 ; 187: v31 = 1035; .text:00401A32 push 40Bh .text:00401A37 jmp short loc_401A40 .text:00401A39 ; --------------------------------------------------------------------------- .text:00401A39 .text:00401A39 loc_401A39: ; CODE XREF: sub_401870+16Ej .text:00401A39 ; sub_401870+17Dj ... .text:00401A39 push 0 ; lParam .text:00401A3B ; 193: v31 = 1034; .text:00401A3B .text:00401A3B loc_401A3B: ; CODE XREF: sub_401870+1C0j .text:00401A3B push 40Ah ; wParam .text:00401A40 ; 188: return PostMessageW(*(HWND *)(v2 + 4), 0x111u, v31, 0); .text:00401A40 .text:00401A40 loc_401A40: ; CODE XREF: sub_401870+1C7j .text:00401A40 push 111h ; Msg .text:00401A45 ; 194: return PostMessageW(*(HWND *)(v2 + 4), 0x111u, v31, 0); .text:00401A45 push dword ptr [ebx+4] ; hWnd .text:00401A48 call ds:PostMessageW
再对沿途进行分析找到两个验证的关键点:
LODWORD(v35) = '5\01'; HIDWORD(v35) = &unk_420050; // 'B\0P' v28 = v3 + 2; v36 = 0; v29 = 0; while ( *((_WORD *)&v35 + v29) == *v28 ) {
判断第3-6字符是否为15PB
if ( *v2 + *((_WORD *)v8 + 9) == 0x63 && *v17 == *v18 + *((_WORD *)v8 + 6) ) return 1;
其余都为数字,且第1,2字符相加值为0x63,最后一位为第2位+6
最后得出注册码为:1215PB8
第二题
首先分析发现与lua相关,提取运行时解密的疑似luac格式数据,
00000000 1B 6C 73 11 00 19 93 0D 0A 1A 0A 04 04 04 08 08 ls ? 00000010 78 56 00 00 00 00 00 00 00 00 00 00 00 28 77 40 xV (w@ 00000020 01 0E 40 54 61 73 6B 42 65 67 69 6E 2E 6C 73 00 @TaskBegin.ls 00000030 00 00 00 00 00 00 00 00 02 02 07 00 00 00 08 40 @ 00000040 40 80 08 C0 40 81 2C 00 00 00 08 00 00 82 2C 40 @€ 繞 , ?@
经过比较确信为lua5.3的编译格式,只是单单改了头部的标志。
修改头部后,再使用github上的luadec工具进行反编译: g_strRegSn = " " g_strRegSnToVerify = "" userRegister = function(strRegSnIn) -- function num : 0_0 , upvalues : _ENV local iRc = -1 g_strRegSn = strRegSnIn g_strRegSnToVerify = fnGetRegSnToVerify() g_strRegSn = fnCalcUserInputRegSnAfterEnc(g_strRegSn) if g_strRegSn == g_strRegSnToVerify then iRc = 1024 end g_strRegSnToVerify = "" return iRc end getRegSnAfterCalc = function(strRegSnIn) -- function num : 0_1 , upvalues : _ENV return g_strRegSn end
发现验证使用了fnGetRegSnToVerify、fnCalcUserInputRegSnAfterEnc两个函数。而这两个函数在程序初始化时注册过,为lua调用c的典型。
if ( sub_41B422(&lpMem, (unsigned int *)&v7, 191) ) { lua_pushfunc(*((_DWORD *)v1 + 4), fnGetRegSnToVerify, 0); lua_setglobal(*((_DWORD *)v1 + 4), lpMem); } if ( lpMem ) sub_41B5B8(lpMem); lpMem = operator new(0x100u); memcpy(lpMem, &unk_42DF64, 0x100u); v7 = 256; if ( sub_41B422(&lpMem, (unsigned int *)&v7, 34) ) { lua_pushfunc(*((_DWORD *)v1 + 4), fnCalcUserInputRegSnAfterEnc, 0); lua_setglobal(*((_DWORD *)v1 + 4), lpMem); }
经过分析,验证过程是加密后的注册码与两个固定字符串亦或后的值是否为fnGetRegSnToVerify获得的值,3个字符串都是定值:
import binascii s1=binascii.a2b_hex("1AABD470AE1A31D74E7F0227DA3AD3C0C7BFA0E2D792F0E5F864D30496AD1741") s2=binascii.a2b_hex("A447980C9E40D7F6EB766E6D7EA33EEBD55130067DC0FB6CC27A43C5A4C9B1FD") s3=binascii.a2b_hex("F591235E8DB087E2AEEEDE9388F2ACA34F9FB7611023FB301969B8ADCE52006C") s="" for i in range(len(s1)): s+=binascii.b2a_hex(chr(ord(s1[i])^ord(s2[i])^ord(s3[i]))) s=s.upper() print s
将加密后的注册码值导入解密函数41b422,运行可得注册码:
#4B7D6F22BDEA61C30BE7B2D92C6B41885D712785BA71F0B92377286CFC36A6D0 #==> #41b422 to decode (data,len,char=0x47) #0018FBA8 00547EA0 ASCII "stK5CKpBsw7TPF45"
第三题:
进过分析,程序进行了混淆。基本的混淆结构为:
push xxx
push ...
sub esp,xx
call toRet
toRet:
push retaddr
ret xx
经过初略统计大致有2、3十个混淆点,感觉不多,就采用了手动去混淆。去混淆后就能进行ida分析了。
算法分两部分:
AES和RSA,RSA部分n为32位整数,很容易分解。
具体解密脚本如下:
# -*- coding:utf-8 -*- from Crypto.Cipher import AES from binascii import b2a_hex, a2b_hex class prpcrypt(): def __init__(self,key): self.key = key self.mode = AES.MODE_ECB #加密函数,如果text不足16位就用空格补足为16位, #如果大于16当时不是16的倍数,那就补足为16的倍数。 def encrypt(self,text): cryptor = AES.new(self.key,self.mode,b'0000000000000000') #这里密钥key 长度必须为16(AES-128), #24(AES-192),或者32 (AES-256)Bytes 长度 #目前AES-128 足够目前使用 length = 16 count = len(text) if count < length: add = (length-count) #\0 backspace text = text + ('\0' * add) elif count > length: add = (length-(count % length)) text = text + ('\0' * add) self.ciphertext = cryptor.encrypt(text) #因为AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题 #所以这里统一把加密后的字符串转化为16进制字符串 return b2a_hex(self.ciphertext) #解密后,去掉补足的空格用strip() 去掉 def decrypt(self,text): cryptor = AES.new(self.key,self.mode,b'0000000000000000') plain_text = cryptor.decrypt(a2b_hex(text)) return plain_text.rstrip('\0') pc = prpcrypt(a2b_hex('0F5F7BCDC0660D587C86D726B1C6AAD103B21285C103A351BBC5733B3AD43635')) #初始化密钥 #e = pc.encrypt(a2b_hex("8E1C8E1C8E1C8E1C8E1C8E1C8E1C8E1C")) #加密 s = b2a_hex(pc.decrypt("C8E5E2C3C439FC0448D80F8B5F738CA9")) #解密 #print e print s # RSA 部分解密 n=4118084881 e=0x10001 i = 2 while (i<n): if (n%i == 0): break i = i + 1 p=i q=n/p print(p,q) #欧几里得算法求D def ext_euclid ( a , b  if (b == 0): return 1, 0, a else: x , y , q = ext_euclid( b , a % b ) x , y = y, ( x - (a // b) * y ) return x, y, q d,d1,d2= ext_euclid(e, (p-1)*(q-1)) print "RSA D:",hex(d) out="" for i in range(len(s)/4): x=int(s[i*4:(i+1)*4],16) y=pow(x,d,n) out+=("%08X"%(y)) print "key:",out #x=pow(0x12345678,e,n) """ key: 3C4F963B039A2C377E02291E3C157AE591BCC1CA0A8F528EB2700AC021FB958D """
第4题:
搞了半天虚拟机部分最后发现关系不大
1.虚拟机
程序采用了和vmp十分相似的虚拟机,以下是手工分析的handler类型:
CMT 0042F1AA,"vm_pop_local8" CMT 0042F1BD,"vm_rdtsc" CMT 0042F1D6,"vm_shl" CMT 0042F206,"vm_nand8" CMT 0042F231,"vm_push_imm16" CMT 0042F25C,"vm_pop16" CMT 0042F27F,"vm_fstsw" CMT 0042F2A2,"vm_shld" CMT 0042F2BE,"vm_nand16" CMT 0042F2E5,"vm_add32" CMT 0042F2FE,"vm_call" CMT 0042F316,"vm_rol8" CMT 0042F33C,"vm_shr32" CMT 0042F354,"vm_ror32" CMT 0042F37A,"vm_ror16" CMT 0042F3A3,"vm_push_imm32" CMT 0042F3CF,"vm_shr8" CMT 0042F400,"vm_push_reg8" CMT 0042F434,"vm_read_addr32" CMT 0042F441,"vm_pop_reg32" CMT 0042F472,"vm_jmp_2" CMT 0042F485,"vm_push_imm8_1" CMT 0042F4A2,"vm_rol_32" CMT 0042F4BA,"vm_add16" CMT 0042F4DE,"vm_read_addr16" CMT 0042F4F6,"vm_push_imm16" CMT 0042F51C,"vm_rol8" CMT 0042F54A,"vm_read_add8" CMT 0042F563,"vm_push_imm8_2" CMT 0042F588,"vm_push_imm16_dec" CMT 0042F5AD,"vm_push_imm8_3" CMT 0042F5C5,"vm_pop_esp" CMT 0042F5DC,"vm_cpuid" CMT 0042F601,"vm_pop_reg16" CMT 0042F623,"vm_push_reg32" CMT 0042F656,"vm_shrd32" CMT 0042F686,"vm_setbx" CMT 0042F697,"vm_write_addr8" CMT 0042F6B5,"vm_push_local32" CMT 0042F6CA,"vm_shl32" CMT 0042F6E3,"vm_pop_local32" CMT 0042F709,"vm_shr16" CMT 0042F727,"vm_dispatcher" CMT 0042F753,"vm_pop_local16" CMT 0042F76F,"vm_exit" CMT 0042F77A,"vm_push_reg16" CMT 0042F790,"vm_ror8" CMT 0042F7C6,"vm_write_addr32" CMT 0042F7E7,"vm_push_reg8" CMT 0042F7FE,"vm_nand32" CMT 0042F831,"vm_push_local_16" CMT 0042F853,"vm_push_esp" CMT 0042F866,"vm_jmp" CMT 0042F87E,"vm_add8" CMT 0042F893,"vm_pop_reg8" CMT 0042F8B7,"vm_shl8"
与vmp相比少了不少指令,执行的指令流也没进过任何的混淆,对efl的读取也是直接通过pushfd。并且使用nand来作为逻辑运算单位。主要的混淆位置是在执行vm_code时通过大量的vm_push和vm_pop。
2.算法
分析后发现是走一个简单的迷宫,迷宫由两部分异或加密:
0019F1F0 6E D4 1B 69 5F 4E E8 AA 95 F6 AF CE 32 1A 62 D9 n?i_N瑾曵2b? 0019F200 02 18 74 95 1F C2 4D 33 3C F0 3B EC E9 81 4B 9C t?翸3<?扉並? 0019F210 0F 47 5C AD D9 09 B0 87 53 9B F2 E3 0F 01 92 8D G\.皣S涷?拲 0019F220 C2 F5 0C DD 42 CC AF B4 D5 E4 86 D3 9A 0B 62 63 迈.軧摊凑鋯託bc 0019F230 A7 D4 1B 69 5F 4E E8 AA 95 F6 AF CE 32 1A 62 D9 гi_N瑾曵2b? 0019F240 02 18 74 95 1F C2 4D 33 38 F0 3B EC ED 81 4B 9C t?翸38?祉並? 0019F250 0B 47 5C AD DD 09 B0 87 57 9B F2 E3 0B 01 92 8D G\.皣W涷?拲 0019F260 C2 F5 0C DD 42 CC AF B4 D5 E4 86 D3 9A 0B 62 63 迈.軧摊凑鋯託bc 0019F270 A7 D4 1B 69 5F 4E E8 AA 95 F6 AF CE 32 1A 62 D9 гi_N瑾曵2b? 0019F280 02 18 74 95 1F C2 4D 33 38 F0 3B EC E9 81 4B 9C t?翸38?扉並? 0019F290 0F 47 5C AD D9 09 B0 87 53 9B F2 E3 0F 01 92 8D G\.皣S涷?拲 0019F2A0 C2 F5 0C DD 42 CC AF B4 D5 E4 86 D3 9A 0B 62 63 迈.軧摊凑鋯託bc 0019F2B0 A7 D4 1B 69 5B 4E E8 AA 91 F6 AF CE 36 1A 62 D9 гi[N瑾戹6b? 0019F2C0 02 18 74 95 1F C2 4D 33 38 F0 3B EC E9 81 4B 9C t?翸38?扉並? 0019F2D0 0B 47 5C AD DD 09 B0 87 57 9B F2 E3 0B 01 92 8D G\.皣W涷?拲 0019F2E0 C6 F5 0C DD 42 CC AF B4 D5 E4 86 D3 9A 0B 62 63 契.軧摊凑鋯託bc 0019F2F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0019F300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0019F310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0019F320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0019F330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0019F340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0019F350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0019F360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0019F370 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0019F380 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0019F390 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0019F3A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0019F3B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0019F3C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0019F3D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0019F3E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0019F3F0 D8 05 F6 6A E7 A2 0B 9B 54 8C DA 82 BD B6 A8 46 ?鰆纰汿屭偨定F 0019F400 B1 36 2D 55 F7 81 63 FC 3F 0C FE 0B 4B 50 E2 17 ?-U鱽c?.?KP? 0019F410 F2 E1 27 5B 46 73 1C D0 E5 D7 8D C9 F2 70 94 53 蜥'[Fs绣讔沈p擲 0019F420 81 4C 32 46 A0 02 DB 1C 45 09 91 C4 96 F2 A8 E8 丩2F??E.懩栻ㄨ 0019F430 D9 05 F6 6B E7 A2 0A 9B 54 8C DA 82 BD B7 A9 46 ?鰇纰.汿屭偨珐F 0019F440 B0 36 2D 54 F7 81 63 FC 3E 0C FE 0B 4B 50 E3 17 ?-T鱽c?.?KP? 0019F450 F2 E0 26 5A 47 73 1C D1 E5 D6 8C C8 F2 70 95 53 蜞&ZGs彦謱闰p昐 0019F460 80 4C 33 47 A0 02 DB 1C 44 08 91 C4 96 F2 A9 E8 €L3G??D懩栻╄ 0019F470 D9 04 F6 6A E7 A2 0A 9B 55 8C DB 83 BC B6 A9 46 ?鰆纰.沀屰兗订F 0019F480 B0 37 2D 55 F7 81 63 FD 3E 0D FE 0B 4A 50 E3 17 ?-U鱽c?.?JP? 0019F490 F3 E0 27 5B 46 73 1D D0 E4 D7 8C C8 F3 70 95 53 筻'[Fs袖讓润p昐 0019F4A0 80 4C 33 47 A0 03 DB 1D 45 08 91 C4 96 F2 A9 E8 €L3G??E懩栻╄ 0019F4B0 D9 04 F6 6A E6 A3 0A 9A 54 8C DB 82 BC B7 A9 46 ?鰆妫.歍屰偧珐F 0019F4C0 B0 37 2C 54 F6 81 62 FD 3E 0D FE 0A 4A 50 E2 17 ?,T鰜b?.?JP? 0019F4D0 F2 E1 27 5B 47 72 1C D0 E5 D7 8C C9 F2 70 94 53 蜥'[Gr绣讓沈p擲 0019F4E0 81 4D 33 47 A0 03 DB 1C 44 08 91 C5 97 9A A8 E8 丮3G??D懪棜ㄨ
解密后=>
43303030303131313131313131303030 31303030303130303030303031303030 31303030303130313131313131303030 31313131303130313030303030303030 30303031303130313131313131313130 30303031303130303030303030303130 30313131303130303030303030303130 30313030303130313131303030303130 30313030303130313031303030303130 30313030303130313031303030303130 30313030303131313031303030303130 30313030303030303031303030303130 30313030303030303031303131313130 30313131313131313031303130303030 30303030303030313031303130303030 30303030303030313131303131583030
30为墙,58为出口,43为入口。
004012EE 83F9 30 cmp ecx,0x30 ; //0x30 说明撞墙了 注册失败 004012F1 0F84 E2000000 je CrackMe.004013D9 004012F7 83F9 20 cmp ecx,0x20 004012FA 0F84 D9000000 je CrackMe.004013D9 00401300 83F9 58 cmp ecx,0x58 ; //0x58 为出口 注册成功 00401303 0F84 E5000000 je CrackMe.004013EE
每两bit为一个操作:
00401248 8A8D 0CFCFFFF mov cl,byte ptr ss:[ebp-0x3F4] 0040124E D3EA shr edx,cl 00401250 83E2 03 and edx,0x3 00401253 FF2495 0C144000 jmp dword ptr ds:[edx*4+0x40140C] 0040125A 83E8 10 sub eax,0x10 0040125D EB 09 jmp short CrackMe.00401268 0040125F 40 inc eax 00401260 EB 06 jmp short CrackMe.00401268 00401262 83C0 10 add eax,0x10 00401265 EB 01 jmp short CrackMe.00401268 00401267 48 dec eax 00401268 8985 30FCFFFF mov dword ptr ss:[ebp-0x3D0],eax
==>
0:up 1:right 2:down 3:left
由此可求得一串操作码。
注册码长30字符分为两部分,先获取前7个字符的MD5值,将MD5值扩展到23位。
c为一串常量
0040102D C785 14FCFFFF 4>mov dword ptr ss:[ebp-0x3EC],0xCC5CAD44//c 00401037 8BF9 mov edi,ecx 00401039 C785 18FCFFFF 1>mov dword ptr ss:[ebp-0x3E8],0x8D739012 00401043 6A 00 push 0x0 00401045 50 push eax 00401046 8BF2 mov esi,edx 00401048 89BD 2CFCFFFF mov dword ptr ss:[ebp-0x3D4],edi 0040104E C785 1CFCFFFF 4>mov dword ptr ss:[ebp-0x3E4],0x89E38147 00401058 C785 20FCFFFF 8>mov dword ptr ss:[ebp-0x3E0],0xF9DF9C84 00401062 C785 24FCFFFF 4>mov dword ptr ss:[ebp-0x3DC],0x9EB66A47 0040106C 66:C785 28FCFFF>mov word ptr ss:[ebp-0x3D8],0x3011 00401075 C685 2AFCFFFF 2>mov byte ptr ss:[ebp-0x3D6],0x27
op是操作码
最终转换的验证为:
MD5_23(key[:7])^c^key[7:]==op
因为程序未设定其他任何条件,所以此处需要枚举前7为,能使后23为的值为可见字符串,具体全流程的脚本如下:
import binascii import md5 p1="6ED41B695F4EE8AA95F6AFCE321A62D9021874951FC24D333CF03BECE9814B9C" p1+="0F475CADD909B087539BF2E30F01928DC2F50CDD42CCAFB4D5E486D39A0B6263" p1+="A7D41B695F4EE8AA95F6AFCE321A62D9021874951FC24D3338F03BECED814B9C" p1+="0B475CADDD09B087579BF2E30B01928DC2F50CDD42CCAFB4D5E486D39A0B6263" p1+="A7D41B695F4EE8AA95F6AFCE321A62D9021874951FC24D3338F03BECE9814B9C" p1+="0F475CADD909B087539BF2E30F01928DC2F50CDD42CCAFB4D5E486D39A0B6263" p1+="A7D41B695B4EE8AA91F6AFCE361A62D9021874951FC24D3338F03BECE9814B9C" p1+="0B475CADDD09B087579BF2E30B01928DC6F50CDD42CCAFB4D5E486D39A0B6263" p2="D805F66AE7A20B9B548CDA82BDB6A846B1362D55F78163FC3F0CFE0B4B50E217" p2+="F2E1275B46731CD0E5D78DC9F2709453814C3246A002DB1C450991C496F2A8E8" p2+="D905F66BE7A20A9B548CDA82BDB7A946B0362D54F78163FC3E0CFE0B4B50E317" p2+="F2E0265A47731CD1E5D68CC8F2709553804C3347A002DB1C440891C496F2A9E8" p2+="D904F66AE7A20A9B558CDB83BCB6A946B0372D55F78163FD3E0DFE0B4A50E317" p2+="F3E0275B46731DD0E4D78CC8F3709553804C3347A003DB1D450891C496F2A9E8" p2+="D904F66AE6A30A9A548CDB82BCB7A946B0372C54F68162FD3E0DFE0A4A50E217" p2+="F2E1275B47721CD0E5D78CC9F2709453814D3347A003DB1C440891C5979AA8E8" pp1=binascii.a2b_hex(p1) pp2=binascii.a2b_hex(p2) pp3="" def ror2(a): return ((a&3)<<6)|(a>>2)&0xFF print hex(ror2(ord(pp1[1]))^ord(pp2[1])) for i in range(len(pp1)): pp3+=chr(ror2(ord(pp1[i]))^ord(pp2[i])) print len(pp1) for i0 in range(16): ps="" for i1 in range(16): ps+=binascii.b2a_hex(pp3[16*i0+i1]).upper() print ps x=0 y=0 xo=-1 yo=-1 t=[(0,-1),(1,0),(0,1),(-1,0)] path="" while(ord(pp3[y*16+x])!=0x58): for i in range(4): xx=x+t[i][0] yy=y+t[i][1] if xx>=0 and xx<16 and yy>=0 and yy<16 and (xx!=xo or yy!=yo): if ord(pp3[yy*16+xx])!=0x30: path+=(str(i)) xo=x yo=y x=xx y=yy break print path,len(path) pn0="" for i in range(23): a=0 for j in range(4): a=(a|int(path[i*4+j])<<((3-j)*2))&0xFF pn0+=chr(a) print binascii.b2a_hex(pn0).upper() def getmd5(src): m1 = md5.new() m1.update(src) ret=m1.digest() ret=ret+ret[0:7] return ret #pm0=getmd5('Crackme') pn1=binascii.a2b_hex("44AD5CCC1290738D4781E389849CDFF9476AB69E113027") pnx="" for i in range(23): pnx+=chr(ord(pn0[i])^ord(pn1[i])) print "pnx:",binascii.b2a_hex(pnx).upper() def xorpm(pm): global pnx pno="" for i in range(23): pno+=chr(ord(pnx[i])^ord(pm[i])) return pno #pno=xorpm(pm0) #print "pno:",binascii.b2a_hex(pno.upper()) #print pno def isstr(s): for a in s: aa=ord(a) if aa<32 or aa>126: return False return True tab='0123456789abcdef' #print isstr(pno) for a0 in tab: for a1 in tab: for a2 in tab: for a3 in tab: for a4 in tab: for a5 in tab: for a6 in tab: aaa=a0+a1+a2+a3+a4+a5+a6 pppp=xorpm(getmd5(aaa)) if isstr(pppp): print aaa+pppp break """ 0:up 1:right 2:down 3:left #result 033a544 9NE6t,iMft0mVbhJmFDdx'= 0c1e344 e9]%GH`"@cgE$o.811\wKC4 10f3797 .;Q <?n+URr@:}D)z3Pr04: 15701ad ;LYskzk(5Zv2"Z9NoDX!gq? 1ddb354 cZ,66,{~2?qAS*VJ7R-d:'/ """
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
赞赏
他的文章
- [原创]看雪CTF2016 1~4题 分析 5140
- [原创]VMP分析handler与脱壳插件&源码 31266
- [原创]闪讯客户端内存泄漏的简单分析 7611
看原图
赞赏
雪币:
留言: