首页
社区
课程
招聘
[原创]看雪 2016 CTF 第二十三 像素扫描
发表于: 2016-12-17 17:33 5717

[原创]看雪 2016 CTF 第二十三 像素扫描

HHHso 活跃值
22
2016-12-17 17:33
5717

程序入口Hi_main_sub_4016B0函数定位窗体相应函数 Hi_DialogFunc_sub_401830
Hi_main_sub_4016B0
.text:004016D7 push    offset Hi_DialogFunc_sub_401830 ; lpDialogFunc
.text:004016DC push    0               ; hWndParent
.text:004016DE push    65h             ; lpTemplateName
.text:004016E0 push    esi             ; hInstance
.text:004016E1 call    ds:CreateDialogParamW

响应函数Hi_DialogFunc_sub_401830分两步
Hi_getKey_sub_401140 获取注册码信息
Hi_checkKey_sub_4017B0 进入校验环节

Hi_getKey_sub_401140获取的注册码信息是注册码字符在
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"中的零起索引数组
长度伪要求"004018BE cmp     eax, 8"不小于8,实际要求固定长度0x12

注册码信息的获取比较特殊,Hi_Hook_GetBoundsRect_sub_401000初始化函数劫持了
API函数 GetBoundsRect 如下,其实际调用为 Hi_GetBoundsRect_sub_401350 函数
而Hi_GetBoundsRect_sub_401350函数的实际作用通过异常转换为 GetPixel 调用
pxyRGB = GetPixel(hdcOfEdit,ch_lt_X+ch_in_x,ch_lt_Y+ch_in_y)
Edit框的字体信息为
CreateFontW(20, 0, 0, 0, 700, 0, 0, 0, 0, 0, 0, 0, 0x31u, L"Courier New")
每一个字符的像素矩阵为0x08*0x0E=0x70
Hi_getKey_sub_401140函数通过GetPixel(以GetBoundsRect为伪装)依次扫描
Edit输入框的0x12个字符的像素矩阵0x08*0x0E=0x70,
字符的像素特征矩阵分别以[0x00,0xFF]之间的随机偶数和奇数描述,
若像素为白素则描述为随机偶数,否则描述为随机奇数
没获取一个字符的像素特征奇偶数矩阵,就会通过
Hi_search_oepa_for_char_in_oepas_sub_4010A0函数进行查表得到字符的索引值,
Hi_oepas_of_09azAZ_byte_4121C0静态依次存储了
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"字符
的像素特征随机奇偶数表示的矩阵,查表时,只有目标矩阵个像素的奇偶数特征都匹配时
则匹配成功。

GetBoundsRect劫持
BOOL Hi_Hook_GetBoundsRect_sub_401000()
{
  flOldProtect = 0;
  VirtualProtect(GetBoundsRect, 5u, 4u, &flOldProtect);
  memcpy_s(&Hi_GetBoundsRect_Head5bytes_dword_414A84, 5u, GetBoundsRect, 5u);
  LongJmpBuf.OpCode = 0xE9 //jmp
  LongJmpBuf.Offset = Hi_GetBoundsRect_sub_401350 - GetBoundsRect - 5;
  memcpy_s(GetBoundsRect, 5u, &LongJmpBuf, 5u);
  result = VirtualProtect(GetBoundsRect, 5u, flOldProtect, &flOldProtect);
  return result;
}
     

注册码信息获取函数伪码
Hi_getKey_sub_401140(key)  //扫描Edit输入框像素矩阵获取注册码信息
{
  hdcOfEdit = GetDC(hWndOfEdit_414A98)
  ch_lt_X=3,ch_lt_Y=4;
  ch_idx = 0
  while True:
    ch_in_y = 0
    while True:
      ch_in_x = 0
      while True:
        pxyRGB = GetPixel(hdcOfEdit,ch_lt_X+ch_in_x,ch_lt_Y+ch_in_y)
        //GetBoundsRect(hdcOfEdit,ch_lt_X+ch_in_x,ch_lt_Y+ch_in_y)
        //GetBoundsRect Longjmp to Hi_GetBoundsRect_sub_401350
        if pxyRGB == WHILE.0x00FFFFFF: //如果像素为白色则以随机偶数表示
          oev = ptd.rand.even inner 0xff
        else:
          oev = ptd.rand.odd inner 0xff //否则以随机偶数奇数表示
        oepa_of_char[ch_in_y*0x8+ch_in_x] = oev
        if ++ch_in_x >= 8:break
      if ++ch_in_y >= 0x0E:break
    ch_lt_X+=0x0A //next char left-top pixel x-pos
    key[ch_idx] = Hi_search_oepa_for_char_in_oepas_sub_4010A0(oepa_of_char)
    if ++ch_idx >= 0x12:break
  return key
}

字符像素特征奇偶数矩阵查表
Hi_search_oepa_for_char_in_oepas_sub_4010A0(oepa_of_char){
  //CharIndex is index of "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  //e.g. CharIndex.0x00 for "0"; CharIndex.0x10 for "g";
  for CharIndex in xrange(0,0x3E):
    oepaX = Hi_oepas_of_09azAZ_byte_4121C0[CharIndex]
    if Is_Odd_Even_Attrib_Of_Each_Element_All_Match(oepaX,oepa_of_char):
      return CharIndex
}

如字符表中第一个字符"0"的像素特殊奇偶数矩阵
for i in xrange(0,0x70):
  print "{:02X}".format(Byte(0x4121c0+i)),
  if (i+1)%8==0:
    print

D5 88 18 28 26 D0 5E 25
6D 48 3E 58 F6 CC C6 2D
C2 C0 E8 6C 5C 4C CE 22
F8 2E 8A DF C5 CE D8 F0
16 4C 30 C1 A3 C4 B0 F0
2C C2 F4 75 63 94 4E 52
E2 20 5A 95 85 3C 7A B0
00 96 E4 59 45 F6 18 12
D4 6E 64 C8 74 7C 00 C6
B7 58 1C E4 92 2C 28 4D
87 5A CA 88 4C 98 32 F1
CD 69 53 47 6F 13 E7 97
DB 93 4B 57 AD EB 8F 4D
D9 29 5D 93 B7 D3 49 33

通过下述代码,我们观察奇偶数矩阵的像素特征
def oec(cv=0,o=" ",e="1"):
  if cv & 1:
    return o
  else:
    return e

def gsc(ea,bp = False):
  nca = []
  ln = ""
  for i in xrange(0,0x70):
    #print oec(Byte(ea+i)),
    ln += oec(Byte(ea+i))
    if (i+1)%8==0:
      if bp:
        print ln
      nca.append(ln)
      ln = ""
  if bp:
    print ln
  nca.append(ln)
  return nca

def sncas(ncas):
  for r in xrange(0,ncas[0].__len__()):
    for nca in ncas:
      print nca[r],
    print

print "-"*0x80
sncas([gsc(0x4121c0)])
print "-"*0x80
上述代码通过oec分别以" "和"1"描述奇偶数,得到字符的像素矩阵的形象特征图形
--------------------------------------------------------------------------------------------------------------------------------
111111
111111
11111111
111  111
111  111
111  111
111  111
111  111
11111111
111111
111111
        
        
        

--------------------------------------------------------------------------------------------------------------------------------
allnca = []
for i in xrange(0,0x3E):
  nca_ea = 0x4121C0 + i*0x70
  allnca.append(gsc(nca_ea))

print "-"*0x80
sncas(allnca[0:0x0a])
print "-"*0x80
sncas(allnca[0x0A:0x0A+0x0E])
print "-"*0x80
sncas(allnca[26+0x0A:0x0A+0x0E+26])
print "-"*0x80
--------------------------------------------------------------------------------------------------------------------------------
111111    1111    111111   111111     1111  11111111    11111 11111111  111111    11111
111111  111111   11111111 11111111   11111  11111111   111111 11111111 11111111  1111111
11111111 111111   111  111 111  111   11111  111       1111    111  111 111  111 1111 111
111  111   1111   111  111      111  111111  111      1111          111 111  111 111   11
111  111   1111       1111   111111  111111  1111111  1111111      111  11111111 1111 111
111  111   1111      1111    111111 1111111  11111111 11111111     111  11111111  1111111
111  111   1111     1111        111 11111111      111 1111 111     111  111  111   111111
111  111   1111    1111         111 11111111      111 111   11    111   111  111      111
11111111   1111   1111     11   111     111  11   111 1111 111    111   111  111     1111
111111  11111111 11111111 11111111   111111 11111111  1111111    111   11111111 1111111
111111  11111111 11111111 1111111    111111  111111    11111    111     111111  111111  
                                                                                         
                                                                                         
                                                                                         
         
--------------------------------------------------------------------------------------------------------------------------------
         111                   1111             11111          111        111       111   111      111111                    
         111                   1111            111111          111        111       111   111      111111                    
         111                    111            111             111                        111        1111                    
1111111  1111111   1111111  1111111  111111  11111111  1111111 1111111  111111   1111111  11111111   1111   11111111 1111111
11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 111111   1111111  11111111   1111   11111111 11111111
     111 1111 111 111   11 111  111 111  111   111    111 1111 1111 111   1111       111  111111     1111   11111111 1111 111
1111111 111   11 11       11   111 11111111   111    11   111 111  111   1111       111  11111      1111   11 11111 111  111
11111111 111   11 11       11   111 11111111   111    11   111 111  111   1111       111  111111     1111   11 11 11 111  111
11   111 111  111 111   11 111  111 11         111    111 1111 111  111   1111       111  1111111    1111   11 11 11 111  111
11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111     111  111 1111 11111111 11 11111 11111111
11111111 1111111   1111111  1111111  1111111 11111111  1111111 11111111 11111111     111  11111111 11111111 11 11111 11111111
                                                           111                       111                                    
                                                       1111111                   1111111                                    
                                                       111111                    111111                                      
            
--------------------------------------------------------------------------------------------------------------------------------
                                                                                                                             
111111   1111111   1111111 1111111  11111111 11111111  1111111 11111111 11111111   111111 11111111 111111   111  111 111  111
111111   11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111   111111 11111111 111111   111  111 1111 111
111111  111  111 111  111 111  111 111  111 1111  11 111   11 111  111   1111        111 111 111   111     111  111 1111 111
111111  111  111 11    11 111  111 11111111 11111111 11       111  111   1111        111 111111    111     11111111 11111111
1111111  11111111 11       111   11 111111   111111   11       11111111   1111        111 111111    111     11111111 11111111
11111111 11111111 11       111   11 111111   111111   11  1111 11111111   1111   11   111 1111111   111  11 11111111 11111111
11111111 111   11 11       111   11 11111111 111111   11  1111 111  111   1111   11   111 111 1111  111  11 11111111 11111111
111  111 111   11 111   11 111  111 111   11 1111     111   11 111  111   1111   111 1111 111  111  111  11 11 11111 111 1111
11111111 11111111 11111111 11111111 11111111 111111   11111111 11111111 11111111 1111111  1111 111 11111111 11111111 111 1111
11111111 11111111  1111111 1111111  11111111 111111    1111111 11111111 11111111  11111   1111  11 11111111 11111111 111  111
                                                                                                                             
                                                                                                                             
                                                                                                                             
            
--------------------------------------------------------------------------------------------------------------------------------

.text:0040189D lea     edx, [esp+40h+var_18_key]
.text:004018A1 mov     [esp+40h+var_18_key], 0
.text:004018A6 movdqu  xmmword ptr [esp+40h+var_18_key+1], xmm0
.text:004018AC push    ecx
.text:004018AD mov     word ptr [esp+44h+var_18_key+11h], 0
.text:004018B4 mov     [esp+44h+var_5], 0
.text:004018B9 call    Hi_getKey_sub_401140
.text:004018BE cmp     eax, 8
.text:004018C1 jb      loc_401960
.text:004018C7 lea     ecx, [esp+40h+var_18_key]
.text:004018CB call    Hi_checkKey_sub_4017B0
.text:004018D0 cmp     eax, 0A466EEEFh

Hi_checkKey_sub_4017B0

.text:004017B0 Hi_checkKey_sub_4017B0 proc near        ; CODE XREF: Hi_DialogFunc_sub_401830+9Bp
.text:004017B0 push    ebx
.text:004017B1 push    esi
.text:004017B2 mov     esi, ecx
.text:004017B4 mov     al, [esi]
.text:004017B6 movzx   edx, byte ptr [esi+1]
.text:004017BA not     al
.text:004017BC movzx   ecx, byte ptr [esi+2]
.text:004017C0 movzx   eax, al
.text:004017C3 mov     ebx, dword ptr Hi_oepas_of_09azAZ_byte_4121C0[eax*4]
.text:004017CA xor     ebx, 0FFFh
.text:004017D0 movzx   eax, bl
.text:004017D3 xor     edx, eax
.text:004017D5 shr     ebx, 8
.text:004017D8 xor     ebx, dword ptr Hi_oepas_of_09azAZ_byte_4121C0[edx*4]
.text:004017DF movzx   eax, bl
.text:004017E2 xor     ecx, eax
.text:004017E4 shr     ebx, 8
.text:004017E7 xor     ebx, dword ptr Hi_oepas_of_09azAZ_byte_4121C0[ecx*4]
.text:004017EE movzx   ecx, byte ptr [esi+3]
.text:004017F2 movzx   eax, bl
.text:004017F5 xor     ecx, eax
.text:004017F7 shr     ebx, 8
.text:004017FA xor     ebx, dword ptr Hi_oepas_of_09azAZ_byte_4121C0[ecx*4]
.text:00401801 cmp     dword ptr [esi+4], 0E361C2Ch
.text:00401808 jnz     short loc_401827
.text:0040180A cmp     dword ptr [esi+8], 150A121Bh
.text:00401811 jnz     short loc_401827
.text:00401813 cmp     dword ptr [esi+0Ch], 0B161E31h
.text:0040181A jnz     short loc_401827
.text:0040181C cmp     dword ptr [esi+10h], 1B0Eh
.text:00401823 jnz     short loc_401827
.text:00401825 not     ebx
.text:00401827
.text:00401827 loc_401827:
.text:00401827 pop     esi
.text:00401828 mov     eax, ebx
.text:0040182A pop     ebx
.text:0040182B retn
.text:0040182B Hi_checkKey_sub_4017B0 endp

byte key[0x12] = {k0,k1,k2,k3,...,k16,k17} = {ww1,ww2,ww3,ww4,w5}
其中 ww2 = 0E361C2Ch;ww3 = 150A121Bh;ww4 = 0B161E31h;w5 = 1B0Eh
即 key417 = k4,k5,...,k17 = {ww2,ww3,ww4,w5}
于是执行下述#-------python代码得到key417_str为"IsSerialNumber"
#-------
key417 =[0x2C,0x1C,0x36,0x0E,0x1B,0x12,0x0A,0x15,0x31,0x1e,0x16,0x0b,0x0e,0x1b]
nazAZ = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
key417_str = b"".join([nazAZ[CharIndex] for CharIndex in key417])
#-------

key的前四字节的校验逻辑为
ebx = Hi_oepas_of_09azAZ_byte_4121C0[~k0]
ebx ^= 0xFFF
dl = k1 ^ bl                     
ebx >> 8
ebx ^= Hi_oepas_of_09azAZ_byte_4121C0[dl]  
cl = k2 ^ bl
ebx >> 8
ebx ^= Hi_oepas_of_09azAZ_byte_4121C0[cl]
cl = k3 ^ bl
ebx >> 8
ebx ^= Hi_oepas_of_09azAZ_byte_4121C0[cl]
not ebx
ebx == 0x0A466EEEFh

直接的方式就是借助k0,k1,k2,k3的取值范围nazAZ
和数组Hi_oepas_of_09azAZ_byte_4121C0直接穷举

这里尝试从校验逻辑进行逆推
在最后一步异或操作中
cl = k3 ^ bl
ebx >> 8
ebx ^= Hi_oepas_of_09azAZ_byte_4121C0[cl]
其中异或结果为 ebx = not 0x0A466EEEFh = 0x5b991110
考虑到异或前ebx>>8,即最高位为0x00;
即cl取值范围[0,0xFF]取出的字的最高字节为 0x5b ^ 0x00 = 0x5b
#-------
def getidxwws(wwhb):
  idxwws = []
  for i in xrange(0,0x100):
    if wwhb == Byte(0x4121C0+i*4+3):
      ww = Dword(0x4121C0+i*4)
      #print "{:02X} {:08X}".format(i,ww)
      idxwws.append([i,ww])
  return idxwws

def sidxwws(idxwws,bxor = None,pref="  "):
  for iww in idxwws:
    if bxor:
      print "{:02X} {:08X} {:08X}".format(iww[0],iww[1],iww[1]^bxor)
    else:
      print "{:02X} {:08X}".format(iww[0],iww[1])

iwws1 = getidxwws(0x5b)
sidxwws(iwws1,0x5b991110)
#-------
-----------------------------------------
执行上面的脚本,我们可以得到cl和对应异或前ebx>>8的可能取值
cl          ebx>>8
58 5BF43274 006D2364
BE 5BDDC935 0044D825
D0 5B1D07CB 008416DB
DC 5BEB9BAF 00728ABF
-----------------------------------------
同理往前逆推,下述cl选出的字最高位分别为上述ebx>>8确定的ebx最高位
可能取值为0x6d,0x44,0x84,0x72
cl = k2 ^ bl
ebx >> 8
ebx ^= Hi_oepas_of_09azAZ_byte_4121C0[cl]
执行
sidxwws(getidxwws(0x6d),0x006D2364<<8)
sidxwws(getidxwws(0x44),0x0044D825<<8)
sidxwws(getidxwws(0x84),0x008416DB<<8)
sidxwws(getidxwws(0x72),0x00728ABF<<8)
得到
58 5BF43274 006D2364  
    cl          ebx>>8
    43 6D407E70 00631A70
    93 6D8D0BB9 00AE6FB9
BE 5BDDC935 0044D825  
    cl          ebx>>8
    22 4438BB05 00E09E05
    8F 440C34F8 00D411F8
D0 5B1D07CB 008416DB ***不存在继续满足帅选的情形***
DC 5BEB9BAF 00728ABF ***不存在继续满足帅选的情形***
-----------------------------------------
同理往前逆推,下述cl选出的字最高位分别为上述ebx>>8确定的ebx最高位
可能取值为0x63,0xAE,0xE0,0xD4
dl = k1 ^ bl                     
ebx >> 8
ebx ^= Hi_oepas_of_09azAZ_byte_4121C0[dl]  
执行
sidxwws(getidxwws(0x63),0x00631A70<<8)
sidxwws(getidxwws(0xAE),0x00AE6FB9<<8)
sidxwws(getidxwws(0xE0),0x00E09E05<<8)
sidxwws(getidxwws(0xD4),0x00D411F8<<8)
得到
58 5BF43274 006D2364  
    43 6D407E70 00631A70
        dl          ebx>>8
        21 634D8C36 0057FC36
        92 633CF238 00268238
        CE 63615599 007B2599
        DD 630B572D 0011272D
    93 6D8D0BB9 00AE6FB9
        dl          ebx>>8
        74 AE2A2F3F 0045963F
BE 5BDDC935 0044D825  
    22 4438BB05 00E09E05 ***不存在继续满足帅选的情形***
    8F 440C34F8 00D411F8
        dl          ebx>>8
        48 D4204AAC 0031B2AC
-----------------------------------------
同理往前逆推,下述cl选出的字最高位分别为上述ebx>>8确定的ebx最高位
可能取值为 0x57,0x26,0x7b,0x11,0x45,0x31
ebx = Hi_oepas_of_09azAZ_byte_4121C0[~k0]
ebx ^= 0xFFF
执行
sidxwws(getidxwws(0x57))
sidxwws(getidxwws(0x26))
sidxwws(getidxwws(0x7b))
sidxwws(getidxwws(0x11))
sidxwws(getidxwws(0x45))
sidxwws(getidxwws(0x31))
得到
~k0   ebx
18    574B93DB
E2    26C6667C
3E    7BEA78EA
6A    7B77D1ED
FA    7BD5254F
D7    31FB64A6
F8    3193FB8B
-----------------------------------------
有上述~k0的取值,我们可以得到相应的k0取值,
执行
not_k0 = [0x18,0xE2,0x3E,0x6A,0xFA,0xD7,0xF8]
for kt in not_k0:
  print "0x{:02X}".format(c_ubyte(~kt).value),
得到~k0对应的k0取值
0xE7 0x1D 0xC1 0x95 0x05 0x28 0x07
由于k0为"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"索引
即k0,k1,k2,k3取值范围都为 [0,0x3D]
即得到k0的可能取值为 0x1D,0x05,0x28,0x07
-----------------------------------------
组合各次逆推过程
58 5BF43274 006D2364  
    43 6D407E70 00631A70
        92 633CF238 00268238
            E2    26C6667C       k0 = ~0xE2 = 0x1D
        CE 63615599 007B2599
            FA    7BD5254F       k0 = ~0xFA = 0x05
BE 5BDDC935 0044D825  
    8F 440C34F8 00D411F8
        48 D4204AAC 0031B2AC
            D7    31FB64A6       k0 = ~0xD7 = 0x28
            F8    3193FB8B       k0 = ~0xF8 = 0x07
-----------------------------------------
对于
58 5BF43274 006D2364  
    43 6D407E70 00631A70
        92 633CF238 00268238
            E2    26C6667C       k0 = ~0xE2 = 0x1D
有k0=0x1d,dl=0x92,ebx=byte_4121C0[~k0] ^ 0xFFF = 0x26c66983 即bl=0x83
-------
ebx = byte_4121C0[~k0]
ebx ^= 0xFFF
dl = k1 ^ bl
所以k1 = bl ^ dl = 0x83 ^ 0x92 = 0x11 属于有效取值范围[0x00,0x0D]
-------
同理,对于
ebx ^= byte_4121C0[dl]
cl = k2 ^ bl
有cl=0x43,ebx=0x26c66983,dl=0x92
ebx ^= byte_4121C0[dl]
后有ebx=0x631a3451,
所以k2 = bl ^ cl = 0x51 ^ 0x43 = 0x12 属于有效取值范围[0x00,0x0D]
-------
同理,对于
(1):ebx ^= byte_4121C0[cl]
(2):cl = k3 ^ bl
有(2):cl=0x58,ebx=0x631a3451,(1):cl=0x43
(1):ebx ^= byte_4121C0[cl]
后ebx=0x6d236444,
所以k3 = bl ^ cl = 0x44 ^ 0x58 = 0x1C 属于有效取值范围[0x00,0x0D]
-------
即 k0,k1,k2,k3 = k03 = [0x1d,0x11,0x12,0x1C]
nazAZ = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
k03_str = b"".join([nazAZ[CharIndex] for CharIndex in k03])
得到k03_str = "this"
-----------------------------------------
同理可以对其它三种情形进行逆推求k0,k1,k2,k3值,
但实际求值过程中都值超过了有效取值范围[0x00,0x0D],丢弃
所以只有k03_str = "this"一种情形
-----------------------------------------

综上所述得到注册码 "thisIsSerialNumber"

另一只IDAPython直接枚举的方式
def getk03str():
  nazAZ = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  ebx = c_ulong(0)
  cl = c_ubyte(0)
  dl = c_ubyte(0)
  kn = c_ubyte(0)
  for k0 in xrange(0,0x3E):
    for k1 in xrange(0,0x3E):
      for k2 in xrange(0,0x3E):
        for k3 in xrange(0,0x3E):
          kn.value = ~k0
          ebx.value = Dword(0x4121C0+4*kn.value)
          ebx.value = ebx.value ^ 0xFFF
          dl.value = k1 ^ ebx.value
          ebx.value = ebx.value >> 8
          ebx.value = ebx.value ^ Dword(0x4121C0+4*dl.value)
          cl.value = k2 ^ ebx.value
          ebx.value = ebx.value >> 8
          ebx.value = ebx.value ^ Dword(0x4121C0+4*cl.value)
          cl.value = k3 ^ ebx.value
          ebx.value  = ebx.value >> 8
          ebx.value = ebx.value ^ Dword(0x4121C0+4*cl.value)
          ebx.value = ~ebx.value
          if ebx.value == 0x0A466EEEF:
            return b"".join([nazAZ[k] for k in [k0,k1,k2,k3]])

            
像素扫描缺陷
由于色差的原因,比如我的系统背底色为浅绿0xB6DEBB,
就与产生致命色差导致无法查表识别输入的字符信息
当输入"thisIsSerialNumber"注册码时,在纯白系统背底下
第一字符的像素矩阵前五个像素色值为左列所示,
而我的浅绿系统背底会在第四个像素产生致命色差,
同理,对于非纯白背底的情形,个别浅色素会被错误识别为白背底而产生致命错误导致无法识别。
ffffff  00B6DEBB <---背景色:纯白 0xffffff,浅绿 0xB6DEBB
b6ffff  00586C5C
000066  00586C5C
db903a  00B6DEBB(致命色差)
ffffff  00B6DEBB

004011E5     3D BBDEB600    CMP EAX,0ffffff
004011E5     3D BBDEB600    CMP EAX,0B6DEBB 修改背景色


[培训]科锐逆向工程师培训第53期2025年7月8日开班!

收藏
免费 1
支持
分享
最新回复 (1)
雪    币: 118
活跃值: (72)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
So Cool,我就说呢,比赛才不是俗套的虚拟机和加壳的战争,它们总是用膨胀和解释来耗费人的尽力。这道题让人看到了出彩。无论是欺诈的函数还是以视觉的方式获取字符都是很不同一般的。
2016-12-18 17:32
0
游客
登录 | 注册 方可回帖
返回