首页
社区
课程
招聘
[原创]看雪CTF.TSRC 2018 团队赛 第四题 WP
2018-12-9 10:35 3023

[原创]看雪CTF.TSRC 2018 团队赛 第四题 WP

2018-12-9 10:35
3023

一、2处反调试
1、如果没有发现反调试则修改D316BD开始2字节为:EB0D,这部分代码如下
signed int sub_DC1010()
{
  HANDLE v0; // eax

  v0 = GetCurrentProcess();
  g_NtQueryInformationProcessAddr(v0, 30, &g_debugFlag, 4, 0);
  return sub_DC1035();
}
signed int sub_DC104F()
{
  signed int result; // eax

  if ( !g_debugFlag )
  {
    loc_D316BD = 0xEBu;
    result = 0xD316BE;
    *(&loc_D316BD + 1) = 0xD;
  }
  return result;
}

.text:00D316BD EB 0D                                               jmp     short loc_D316CC
.text:00D316BD                                     ; ---------------------------------------------------------------------------
.text:00D316BF AC                                                  db 0ACh
.text:00D316C0 DB                                                  db 0DBh
.text:00D316C1 DA                                                  db 0DAh
.text:00D316C2                                     ; ---------------------------------------------------------------------------
.text:00D316C2 FF 15 00 A0 DD 00                                   call    ds:IsDebuggerPresent
  如果没发现反调试则直接跳转,不过这不影响分析,因为主要check函数在这上面
2  如下:
.text:00D31D63 64 A1 18 00 00 00                                   mov     eax, large fs:18h
.text:00D31D69 85 5D EC                                            test    [ebp-14h], ebx
.text:00D31D6C 90                                                  nop
.text:00D31D6D 8B 40 30                                            mov     eax, [eax+30h]
.text:00D31D70 F5                                                  cmc
.text:00D31D71 0F BA E3 0C                                         bt      ebx, 0Ch
.text:00D31D75 0F B6 40 02                                         movzx   eax, byte ptr [eax+2] ;如果存在调试 EAX=1
   如果上面的EAX=1 则会影响下面的地址计算。
二、main
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char sn[32]; // [esp+0h] [ebp-28h]

  std::cout(aPlzInputYourSe, sn[0]);
  GetInputSn(a32s, (unsigned int)sn);
  if ( check(sn) )
    std::cout(aCongratulation, sn[0]);
  else
    std::cout(aWrongSerialYou, sn[0]);
  sub_DCA68B(aPause);
  return 0;
}
1、读取sn sn缓冲区大小为32字节。
2、check函数返回1表示校验成功。
三、check函数
BOOL __cdecl check(char *sn)
{
  char sn1[8]; // [esp+10h] [ebp-1D0h]
  int i; // [esp+18h] [ebp-1C8h]
  char v5[64]; // [esp+1Ch] [ebp-1C4h]
  char v6[64]; // [esp+5Ch] [ebp-184h]
  char v7[64]; // [esp+9Ch] [ebp-144h]
  char v8[256]; // [esp+DCh] [ebp-104h]

  *(_DWORD *)sn1 = 0;
  *(_DWORD *)&sn1[4] = 0;
  sub_DC2140((__m128i *)v7, 0, 0x40u);
  *(_DWORD *)v8 = 0;
  *(_DWORD *)&v8[196] = 0;
  *(_DWORD *)&v8[200] = 0;
  *(_DWORD *)&v8[204] = 0;
  *(_DWORD *)&v8[208] = 10;
  *(_DWORD *)&v8[212] = 15;
  *(_DWORD *)&v8[216] = 2;
  *(_DWORD *)&v8[220] = 13;
  *(_DWORD *)&v8[224] = 10;
  *(_DWORD *)&v8[228] = 8;
  *(_DWORD *)&v8[232] = 6;
  *(_DWORD *)&v8[236] = 15;
  *(_DWORD *)&v8[240] = 0;
  *(_DWORD *)&v8[244] = 5;
  *(_DWORD *)&v8[248] = 3;
  *(_DWORD *)&v8[252] = 0;
  *(_DWORD *)&v8[128] = 16;
  *(_DWORD *)&v8[132] = 0;
  *(_DWORD *)&v8[136] = 16;
  *(_DWORD *)&v8[140] = 14;
  *(_DWORD *)&v8[144] = 3;
  *(_DWORD *)&v8[148] = 10;
  *(_DWORD *)&v8[152] = 6;
  *(_DWORD *)&v8[156] = 0;
  *(_DWORD *)&v8[160] = 0;
  *(_DWORD *)&v8[164] = 7;
  *(_DWORD *)&v8[168] = 13;
  *(_DWORD *)&v8[172] = 6;
  *(_DWORD *)&v8[176] = 4;
  *(_DWORD *)&v8[180] = 7;
  *(_DWORD *)&v8[184] = 0;
  *(_DWORD *)&v8[188] = 2;
  *(_DWORD *)&v8[64] = 6;
  *(_DWORD *)&v8[68] = 16;
  *(_DWORD *)&v8[72] = 0;
  *(_DWORD *)&v8[76] = 12;
  *(_DWORD *)&v8[80] = 0;
  *(_DWORD *)&v8[84] = 11;
  *(_DWORD *)&v8[88] = 16;
  *(_DWORD *)&v8[92] = 12;
  *(_DWORD *)&v8[96] = 8;
  *(_DWORD *)&v8[100] = 12;
  *(_DWORD *)&v8[104] = 12;
  *(_DWORD *)&v8[108] = 0;
  *(_DWORD *)&v8[112] = 6;
  *(_DWORD *)&v8[116] = 0;
  *(_DWORD *)&v8[120] = 11;
  *(_DWORD *)&v8[124] = 13;
  *(_DWORD *)v8 = 16;
  *(_DWORD *)&v8[4] = 14;
  *(_DWORD *)&v8[8] = 13;
  *(_DWORD *)&v8[12] = 14;
  *(_DWORD *)&v8[16] = 4;
  *(_DWORD *)&v8[20] = 0;
  *(_DWORD *)&v8[24] = 0;
  *(_DWORD *)&v8[28] = 16;
  *(_DWORD *)&v8[32] = 5;
  *(_DWORD *)&v8[36] = 0;
  *(_DWORD *)&v8[40] = 0;
  *(_DWORD *)&v8[44] = 3;
  *(_DWORD *)&v8[48] = 5;
  *(_DWORD *)&v8[52] = 16;
  *(_DWORD *)&v8[56] = 14;
  *(_DWORD *)&v8[60] = 16;
  sub_DC2140((__m128i *)v5, 0, 0x40u);
  *(_DWORD *)v6 = 222105;
  *(_DWORD *)&v6[4] = 494358;
  *(_DWORD *)&v6[8] = 443201;
  *(_DWORD *)&v6[12] = 423901;
  *(_DWORD *)&v6[16] = 310311;
  *(_DWORD *)&v6[20] = 700114;
  *(_DWORD *)&v6[24] = 629640;
  *(_DWORD *)&v6[28] = 620483;
  *(_DWORD *)&v6[32] = 301566;
  *(_DWORD *)&v6[36] = 676368;
  *(_DWORD *)&v6[40] = 606711;
  *(_DWORD *)&v6[44] = 605590;
  *(_DWORD *)&v6[48] = 149250;
  *(_DWORD *)&v6[52] = 339264;
  *(_DWORD *)&v6[56] = 304846;
  *(_DWORD *)&v6[60] = 301296;
  if ( strlen(sn) != 16 )
    return 0;
  for ( i = 0; i < 16; ++i )
  {
    if ( (sn[i] < 48 || sn[i] > 57) && (sn[i] < 65 || sn[i] > 70) )
      return 0;
  }
  for ( i = 0; i < 8; ++i )
  {
    if ( sn[i] < 48 || sn[i] > 57 )
      *(_DWORD *)sn1 += (sn[i] - 55) << (28 - 4 * i);
    else
      *(_DWORD *)sn1 += (sn[i] - 48) << (28 - 4 * i);
    if ( sn[i + 8] < 48 || sn[i + 8] > 57 )
      *(_DWORD *)&sn1[4] += (sn[i + 8] - 55) << (28 - 4 * i);
    else
      *(_DWORD *)&sn1[4] += (sn[i + 8] - 48) << (28 - 4 * i);
  }
  sub_D31C70(
    sn1,
    aOneShallStandA,
    0x67452301,
    0xEFCDAB89,
    0x98BADCFE,
    0x10325476,
    0x7380166F,
    0x4914B2B9,
    0x172442D7,
    0xDA8A0600,
    &v8[192],
    0xDEADBEEF);
  sub_D93120();
  return *(_DWORD *)sn1 == 0x87654321 && *(_DWORD *)&sn1[4] == 0x12345678;
}
1、前面一大堆初始化的数据没啥用。
2、判断sn长度不等16则返回0
3、判断sn 是否是 0-9 A-F,不是返回0
4、将输入的字符串转换成2个int整数。
5、然后调用压入了貌似各种加密算法的数据以及一个字符串"One shall stand and one shall fall",不是你死就是我亡。
6、这些数据有的像MD5,有的像SM3,各种算法;
7、调用sub_D31C70
8、然后判断sn1 == 0x87654321  sn2 == 0x12345678,如果相等,则返回真。因此 sub_D31C70会将sn加密。

四、 sub_D31C70加密函数
(一)垃圾指令与SMC
    1、进去这个函数好大, 将近40K ,IDA没法识别。各种垃圾指令,而且还存在SMC,自修改代码。但是稍微分析下这些垃圾指令还是有规律的,比如:
;取出参数局部变量.

text:00D31C91 BF 77 88 8C 60                                      mov     edi, 608C8877h
.text:00D31C96 81 EF A9 A3 67 D3                                   sub     edi, 0D367A3A9h
.text:00D31C9C 81 EF 61 55 D2 99                                   sub     edi, 99D25561h
.text:00D31CA2 81 EF 39 16 BF F8                                   sub     edi, 0F8BF1639h
.text:00D31CA8 81 EF 03 5E 7B 5E                                   sub     edi, 5E7B5E03h
.text:00D31CAE 8B 8C FD 8C 26 3F 1F                                mov     ecx, [ebp+edi*8+1F3F268Ch] ; sn1
 2、SMC自修改代码
                                       push eax
                                        ----------
                                       push ebx
                                        -----------
                                       push ecx

                                       一直到
                                      pop     ecx
                                      pop     ebx
                                      pop     eax
     代码解密结束。
  
.text:00D31F3B 50                                                  push    eax
.text:00D31F3C 83 C9 00                                            or      ecx, 0
.text:00D31F3F FC                                                  cld
.text:00D31F40 53                                                  push    ebx
.text:00D31F41 FC                                                  cld
.text:00D31F42 F5                                                  cmc
.text:00D31F43 51                                                  push    ecx
.text:00D31F44 85 F8                                               test    eax, edi
.text:00D31F46 90                                                  nop
.text:00D31F47 64 A1 18 00 00 00                                   mov     eax, large fs:18h
.text:00D31F4D 39 EB                                               cmp     ebx, ebp
.text:00D31F4F 83 E1 FF                                            and     ecx, 0FFFFFFFFh
.text:00D31F52 8B 40 30                                            mov     eax, [eax+30h]
.text:00D31F55 F7 C3 2C 0B EE 23                                   test    ebx, 23EE0B2Ch
.text:00D31F5B F5                                                  cmc
.text:00D31F5C 0F B6 40 02                                         movzx   eax, byte ptr [eax+2]
.text:00D31F60 90                                                  nop
.text:00D31F61 81 FD 84 48 6F 2D                                   cmp     ebp, 2D6F4884h
.text:00D31F67 BB 00 00 00 00                                      mov     ebx, 0
.text:00D31F6C
.text:00D31F6C                                     loc_D31F6C:                             ; CODE XREF: .text:00D31F7D↓j
.text:00D31F6C 43                                                  inc     ebx
.text:00D31F6D 39 C7                                               cmp     edi, eax
.text:00D31F6F F9                                                  stc
.text:00D31F70 83 C3 01                                            add     ebx, 1
.text:00D31F73 F5                                                  cmc
.text:00D31F74 85 55 9C                                            test    [ebp-64h], edx
.text:00D31F77 81 FB DA 94 0E 00                                   cmp     ebx, 0E94DAh
.text:00D31F7D 72 ED                                               jb      short loc_D31F6C
.text:00D31F7F E8 00 00 00 00                                      call    $+5
.text:00D31F84 5E                                                  pop     esi
.text:00D31F85 01 C6                                               add     esi, eax
.text:00D31F87 81 C6 70 E5 6C 88                                   add     esi, 886CE570h
.text:00D31F8D 81 C6 D6 30 78 14                                   add     esi, 147830D6h
.text:00D31F93 81 C6 08 55 23 93                                   add     esi, 93235508h
.text:00D31F99 81 C6 29 52 56 EB                                   add     esi, 0EB565229h
.text:00D31F9F 81 C6 C0 42 A1 E4                                   add     esi, 0E4A142C0h
.text:00D31FA5 FF E6                                               jmp     esi
.text:00D31FA5                                     ; ---------------------------------------------------------------------------
.text:00D31FA7 2B                                                  db  2Bh ; +
.text:00D31FA8                                     ; ---------------------------------------------------------------------------
.text:00D31FA8 55                                                  push    ebp
.text:00D31FA9 1C 8B                                               sbb     al, 8Bh
.text:00D31FAB 55                                                  push    ebp
.text:00D31FAC F8                                                  clc
.text:00D31FAD 03 55 F4                                            add     edx, [ebp-0Ch]
.text:00D31FB0 8B 55 FC                                            mov     edx, [ebp-4]
.text:00D31FB3 C1 E2 04                                            shl     edx, 4
.text:00D31FB6 31 D0                                               xor     eax, edx
.text:00D31FB8 C1 E0 05                                            shl     eax, 5
.text:00D31FBB B9 C4 00 00 00                                      mov     ecx, 0C4h
.text:00D31FC0 E8 00 00 00 00                                      call    $+5
.text:00D31FC5 58                                                  pop     eax
.text:00D31FC6 83 C0 71                                            add     eax, 71h
.text:00D31FC9 83 E8 0B                                            sub     eax, 0Bh
.text:00D31FCC 32 08                                               xor     cl, [eax]
.text:00D31FCE 83 E8 0E                                            sub     eax, 0Eh
.text:00D31FD1 02 08                                               add     cl, [eax]
.text:00D31FD3 83 E8 09                                            sub     eax, 9
.text:00D31FD6 32 08                                               xor     cl, [eax]
.text:00D31FD8 83 E8 0E                                            sub     eax, 0Eh
.text:00D31FDB 02 08                                               add     cl, [eax]
.text:00D31FDD 83 E8 0A                                            sub     eax, 0Ah
.text:00D31FE0 32 08                                               xor     cl, [eax]
.text:00D31FE2 83 E8 09                                            sub     eax, 9
.text:00D31FE5 32 08                                               xor     cl, [eax]
.text:00D31FE7 83 E8 0C                                            sub     eax, 0Ch
.text:00D31FEA 2A 08                                               sub     cl, [eax]
.text:00D31FEC 83 E8 0B                                            sub     eax, 0Bh
.text:00D31FEF 02 08                                               add     cl, [eax]
.text:00D31FF1 83 E8 0B                                            sub     eax, 0Bh
.text:00D31FF4 02 08                                               add     cl, [eax]
.text:00D31FF6 83 E8 08                                            sub     eax, 8
.text:00D31FF9 2A 08                                               sub     cl, [eax]
.text:00D31FFB E8 00 00 00 00                                      call    $+5
.text:00D32000 58                                                  pop     eax
.text:00D32001 83 C0 36                                            add     eax, 36h
.text:00D32004 83 C0 0B                                            add     eax, 0Bh
.text:00D32007 28 08                                               sub     [eax], cl
.text:00D32009 83 C0 0B                                            add     eax, 0Bh
.text:00D3200C 28 08                                               sub     [eax], cl
.text:00D3200E 83 C0 07                                            add     eax, 7
.text:00D32011 30 08                                               xor     [eax], cl
.text:00D32013 83 C0 0C                                            add     eax, 0Ch
.text:00D32016 28 08                                               sub     [eax], cl
.text:00D32018 83 C0 07                                            add     eax, 7
.text:00D3201B 30 08                                               xor     [eax], cl
.text:00D3201D 83 C0 0F                                            add     eax, 0Fh
.text:00D32020 30 08                                               xor     [eax], cl
.text:00D32022 83 C0 09                                            add     eax, 9
.text:00D32025 00 08                                               add     [eax], cl
.text:00D32027 83 C0 0C                                            add     eax, 0Ch
.text:00D3202A 00 08                                               add     [eax], cl
.text:00D3202C 83 C0 07                                            add     eax, 7
.text:00D3202F 00 08                                               add     [eax], cl
.text:00D32031 83 C0 09                                            add     eax, 9
.text:00D32034 28 08                                               sub     [eax], cl
.text:00D32036 59                                                  pop     ecx
.text:00D32037 5B                                                  pop     ebx
.text:00D32038 58                                                  pop     eax
         可以写个脚本从push ecx 下面开直接跳转到pop ecx位置。不想分析SMC解密算法了,可以先让程序执行一遍,等待代码解密完成,然后用脚本将解密代码跳过,再重新跳转到输入SN位置,再次输入SN,进行分析。下面是相关脚本:
import struct
from idaapi import *
from idc import *
from idautils import *

'''====================================================
函数名:GetLibAddr
用  途:根据模块名获得模块起始地址
备  注:此函数在SHT被破坏时将不起作用
====================================================='''
def GetLibAddr(targetName):
    targetBase = 0
    for i in Modules():
        #print i.name
        if targetName in i.name:
            targetBase = int("%x"%(i.base), 16)
            #print 'targetName:=' + targetName + 'targetBase:=' + str(targetBase)
            break
    if targetBase == 0:
        #print 'targetBase None!!!'
        return False

    return targetBase

'''====================================================
函数名:GetSegAddrByName
用  途:根据段名获得段的起始地址
备  注:
====================================================='''
def GetSegAddrByName(targetName):
    tempAddr = FirstSeg()
    while tempAddr!=0:
        if tempAddr == 0:
            break
        name = SegName(tempAddr)
        if targetName in name:
            return tempAddr
        tempAddr = NextSeg(tempAddr)
    return 0

'''====================================================
函数名:writeMemoryForAddr
用  途:向模块地址写入指定shellcode
备  注:
====================================================='''
def writeMemoryForAddr(targetName, offset, buf):
    targetBase = 0
    targetBase = GetSegAddrByName(targetName)
    if targetBase == 0:
        #print 'targetBase None!!!'
        return False

    addr = targetBase + offset
    if not dbg_write_memory(addr, buf):
        return False

    refresh_debugger_memory()
    return True


'''====================================================
函数名:FindData
用  途:从指定位置查找指定字节的数据
备  注:返回第一个找到的位置
====================================================='''
def FindData(addr, target):
    a = -1
    segStart = SegStart(addr)
    segEnd = SegEnd(addr)
    len=segEnd-segStart
    for i in range(len):
        rawdex1 = idaapi.dbg_read_memory(addr, 1024)
        a = rawdex1.find(target)
        if a>= 0:
            a = a + addr
            break;
        addr = addr+512
    return a

'''====================================================
函数名:makeAllCode
用  途:设置为代码
备  注:返回第一个找到的位置
====================================================='''
def makeAllCode(ea, len):
    while ea < ea + len:
        print str(hex(ea))
        MakeCode(ea)
        instring = GetDisasm(ea)
        inslen = ida_ua.decode_insn(insn, ea)
        print instring
        ea = ea + inslen


print 'start'

startAddr = GetLibAddr('transformer.exe') + 0x1C70
endAddr = startAddr + 0x5A38C
cnt = 0
pushEcxString = 'push    ecx'
jmpEaxString = 'jmp     esi'
wireCode = '\x58\x83\xC0\x36\x83\xC0\x0E\x28\x08\x83\xC0\x0E\x28\x08\x83\xC0'
libAddr = GetLibAddr('transformer.exe')
writeAddr = libAddr + 0x8741;
pushEcxAddr = 0
lastpopAddr = startAddr

print 'jmpLoopAddr = ' + str(hex(libAddr + 0x1B2C))
dbg_write_memory(libAddr + 0x1B2C, '\xeb\xd2')
refresh_debugger_memory()

print 'antiDebugAddr = ' + str(hex(libAddr + 0x6bd))
dbg_write_memory(libAddr + 0x16bd, '\xeb\x0d')
refresh_debugger_memory()

while startAddr < endAddr:
    popAddr = FindData(startAddr, '\x59\x5b\x58')
    print 'prepopAddr = ' + str(hex(lastpopAddr))
    print 'curpopAddr = ' + str(hex(popAddr))
    if 0 == popAddr :
        print 'find ok'
        break;

    flag = 0
    while lastpopAddr < popAddr:
        instring = GetDisasm(lastpopAddr)
        if instring == jmpEaxString:
            MakeCode(lastpopAddr + 2)
        if instring == pushEcxString:
            pushEcxAddr = lastpopAddr
            flag = 1
            break
        lastpopAddr = lastpopAddr + 1

    if flag == 0 :
        print 'no find push ecx'
        break
    lastpopAddr = popAddr
    print 'pushAddr = ' + str(hex(pushEcxAddr))
    offset = popAddr - pushEcxAddr - 6;
    opcode = '\xE9' + struct.pack('I', offset)
    dbg_write_memory(pushEcxAddr + 1, opcode)
    refresh_debugger_memory()
    break;
    cnt = cnt + 1
    startAddr = popAddr + 3

print cnt
print 'finish'
       一共发现600多处自修改的地方  ,而且在偏移0x8741位置的代码执行完又被后面的改了,当时以为其执行完会破坏以前的代码。但是好像就这一处。因此
先将这个被修改的代码改回来执行脚本
可以先使用 MakeAllCode跑一下,让IDA将数据识别成代码,然后再执行(指令修改)。
      注(在算法要结束位置,程序将计算出来的一些临时数据写入到 0x8745偏移一共16个BYTE,貌似没啥用处)。
      执行完后发现代码仍然很大,没时间再简化了,就放弃了,还是直接分析吧。。。。
(二)  sub_D31C70分析
   1、直接上OD调试。在输入SN位置下访问断点、写入断点,可以很块定位到核心算法位置。
00B284B6   .  89847D DEE3E3>mov dword ptr ss:[ebp+edi*2-0x121C1C22],eax
00B284BD   .  85C1          test ecx,eax
00B284BF   .  BF 31987B38   mov edi,0x387B9831
00B284C4   .  81EF 2BE69E53 sub edi,0x539EE62B
00B284CA   .  81EF 3065DE2B sub edi,0x2BDE6530
00B284D0   .  C7847D 486603>mov dword ptr ss:[ebp+edi*2-0x71FC99B8],0x0
00B284DB   .  BF 4BAE0B01   mov edi,0x10BAE4B                                  ;  UNICODE "一"
00B284E0   .  81EF 4504CB80 sub edi,0x80CB0445
00B284E6   .  81EF EDDCB6C5 sub edi,0xC5B6DCED
00B284EC   .  81EF BBC4D83C sub edi,0x3CD8C4BB
00B284F2   .  81EF 9C09F68E sub edi,0x8EF6099C
00B284F8   .  C784BD DC0414>mov dword ptr ss:[ebp+edi*4+0x451404DC],0x89ABCDEF
00B28503   .  BF 5BBDAB83   mov edi,0x83ABBD5B
00B28508   .  81EF C05401A2 sub edi,0xA20154C0
00B2850E   .  81EF 80FEEEBA sub edi,0xBAEEFE80

 发现将SN存储到局部变量中如下:
00DAF5E0  00B28281  返回到 transfor.00B28281 来自 transfor.00B28281
00DAF5E4  00000004
00DAF5E8  12345678   ;sn2
00DAF5EC  12345678   ;sn1
00DAF5F0  00DAF808
00DAF5F4  00B016B5  返回到 transfor.00B016B5 来自 transfor.00B01C70
00DAF5F8  00DAF638
00DAF5FC  00BB1000  ASCII "One shall stand and one shall fall."
00DAF600  67452301
00DAF604  EFCDAB89
00DAF608  98BADCFE
00DAF60C  10325476
00DAF610  7380166F
00DAF614  4914B2B9
00DAF618  172442D7
00DAF61C  DA8A0600
00DAF620  00B08741  transfor.00B08741
00DAF624  63BFC7EA

 这个函数的大概流程如下:
  1、反调试,然后代码自解密;
  2、前面大片都是垃圾代码;
  3、可以对SN下访问断点开始跟踪;
  4、写入多个常量数据到堆栈;
  5、从上面写入的多个常量数据中取出2个用于运算使用,此时堆栈结构如下:
007CF9C0  12345678 //中间用于运算的 实际没有,最后这个值写入到  0x8745偏移地址
007CF9C4  AAAAAAAA //中间用于运算的 实际没有,最后这个值写入到  0x8745偏移地址
007CF9C8  20646E61 //One shall stand and one shall fall中的
007CF9CC  7473206C //One shall stand and one shall fall中的
007CF9D0  20656E4F //One shall stand and one shall fall中的
007CF9D4  89ABCDEF //用于计算的slat
007CF9D8  6C616873 //One shall stand and one shall fall中的
007CF9DC  B4FB26B3  //从前面写入的多个常量数据中取出
007CF9E0  EB0B932A  ////从前面写入的多个常量数据中取出
007CF9E4  89ABCDEF	//用于计算的slat
007CF9E8  AAAAAAAA   输入sn2    //加密数据
007CF9EC  12345678   输入sn1    //加密数据
6、算法比较简单,就是混淆的比较多,耐心分析一下,流程还是很简单的。下面是逆向出来的源码,其中一些用于加密的常量是中间计算出来,我列在下面算法中。
7、先逆向出来加密算法,解密算法就很简单了。

bool encodeData(unsigned int  sn1, unsigned int sn2, int* outSn)
{
		unsigned int tempKey1;
		unsigned int tempKey2;
		unsigned int tempKey3;
		unsigned int key1 = sn1;
		unsigned int key2 = sn2;
		unsigned int str1 = 0x20656E4F;
		unsigned int str2 = 0x6C616873;
		unsigned int str3 = 0x7473206C;
		unsigned int str4 = 0x20646E61;
		unsigned int salt = 0x89ABCDEF;
		unsigned int sn1Salt[8] = { 0xC3DABC80, 0x5EEA6480, 0x70DAFF, 0x98274F00, 0x0C412072, 0x369607A0, 0x30AA34 };
		unsigned int sn2Salt[8] = { 0x00325E4D, 0x1724D6F7, 0x32A48390, 0x3623FDE0, 0x2DC55FB, 0x0393E1BB, 0xABB89880};
		
		for(int i = 0; i < 8; i++)
		{
			tempKey1 = (key2 << 4) + str1;
			tempKey2 = key2 + salt;
			tempKey1 = tempKey1 ^ tempKey2;
			tempKey3 = (key2 >> 5) +str2;;
			tempKey1 = tempKey1 ^ tempKey3;
			key1  += tempKey1;

			tempKey1 = (key1 << 4) + str3;					
			tempKey2 = key1;							
			tempKey2 = key1 + salt;
			tempKey1 = tempKey1 ^ tempKey2;										
			tempKey3 = (key1 >> 5) + str4;			
			tempKey1 = tempKey1 ^ tempKey3;
			key2 += tempKey1;

			if (i < 7)
			{
				key1 = key1 - sn1Salt[i];
				key2 = key2 - sn2Salt[i];
			}
			salt = salt + 0x89ABCDEF;
		}

		outSn[0] = key1;
		outSn[1] = key2;
		return false;
}

bool decryptData(unsigned int  sn1, unsigned int sn2, int* outSn)
{
	unsigned int tempKey1;
	unsigned int tempKey2;
	unsigned int tempKey3;
	unsigned int key1 = sn1;
	unsigned int key2 = sn2;
	unsigned int str1 = 0x20656E4F;
	unsigned int str2 = 0x6C616873;
	unsigned int str3 = 0x7473206C;
	unsigned int str4 = 0x20646E61;
	unsigned int salt = 0x4D5E6F78;
	unsigned int sn1Salt[8] = { 0xC3DABC80, 0x5EEA6480, 0x70DAFF, 0x98274F00, 0x0C412072, 0x369607A0, 0x30AA34 };
	unsigned int sn2Salt[8] = { 0x00325E4D, 0x1724D6F7, 0x32A48390, 0x3623FDE0, 0x2DC55FB, 0x0393E1BB, 0xABB89880 };

	for (int i = 7; i >= 0; i--)
	{
		tempKey1 = (key1 << 4) + str3;
		tempKey2 = key1;
		tempKey2 = key1 + salt;
		tempKey1 = tempKey1 ^ tempKey2;
		tempKey3 = (key1 >> 5) + str4;
		tempKey1 = tempKey1 ^ tempKey3;
		key2 -= tempKey1;

		tempKey1 = (key2 << 4) + str1;
		tempKey2 = key2 + salt;
		tempKey1 = tempKey1 ^ tempKey2;
		tempKey3 = (key2 >> 5) + str2;;
		tempKey1 = tempKey1 ^ tempKey3;
		key1 -= tempKey1;

		if (i > 0)
		{
			key2 += sn2Salt[i-1];
			key1 += sn1Salt[i-1];	
		}
		salt = salt - 0x89ABCDEF;
	}

	outSn[0] = key1;
	outSn[1] = key2;
	return false;
}
   
 SN =  285764B86F41B019




[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

最后于 2018-12-9 14:00 被oooAooo编辑 ,原因:
收藏
点赞4
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回