首页
社区
课程
招聘
[原创]看雪CTF2016 1~4题 分析
发表于: 2016-11-9 15:12 5138

[原创]看雪CTF2016 1~4题 分析

2016-11-9 15:12
5138
第一题:
进过分析程序通过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:'/




"""

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 9
活跃值: (180)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
2
学习,正在研究中,感谢
2016-11-15 21:56
0
游客
登录 | 注册 方可回帖
返回
//