姚小宝 发表于 2018-9-22 22:34

九月份安恒杯月赛之NewDriver

本帖最后由 yechen123 于 2018-9-24 17:13 编辑

这道题解了好久发现大佬48分钟拿下了一血 果然还是自己太菜了
果然还是得多练 以后练多一点发多一点帖子

先上传附件

链接: https://pan.baidu.com/s/1aO55f6nJ2UOpfukyJanovA 提取码: adjt没有CB看这里

PS:如果想找到快速解题的方法 可以看看评论区各位大佬的方法 如果想一步一步调出来 也可以看看这个帖子

无壳 直接用ida打开分析

有个flag但是明显不是正确的flag猜测后面会用的上 先记着

f5显示分析失败应该出题人动了手脚 对这个分析不深
用od分析试试

查找字符发现有input flag:

直接定位关键点代码

00D41280   $55            push ebp
00D41281   .8BEC          mov ebp,esp
00D41283   .81EC 38020000 sub esp,238
00D41289   .A1 0030D400   mov eax,dword ptr ds:
00D4128E   .33C5          xor eax,ebp
00D41290   .8945 FC       mov dword ptr ss:,eax
00D41293   .53            push ebx
00D41294   .56            push esi
00D41295   .57            push edi
00D41296   .68 FF000000   push 0FF                                 ; /n = FF (255.)
00D4129B   .8D85 C9FDFFFF lea eax,dword ptr ss:         ; |
00D412A1   .6A 00         push 0                                 ; |c = 00
00D412A3   .50            push eax                                 ; |s
00D412A4   .C685 C8FDFFFF>mov byte ptr ss:,0            ; |
00D412AB   .E8 E4080000   call <jmp.&MSVCR100.memset>            ; \memset
00D412B0   .B9 08000000   mov ecx,8
00D412B5   .BE 9421D400   mov esi,5ba358a4.00D42194                ;flag{this_is_not_the_flag_hahaha}
00D412BA   .8DBD C8FEFFFF lea edi,dword ptr ss:
00D412C0   .F3:A5         rep movs dword ptr es:,dword ptr ds>
00D412C2   .68 DE000000   push 0DE                                 ; /n = DE (222.)
00D412C7   .8D8D EAFEFFFF lea ecx,dword ptr ss:         ; |
00D412CD   .6A 00         push 0                                 ; |c = 00
00D412CF   .51            push ecx                                 ; |s
00D412D0   .66:A5         movs word ptr es:,word ptr ds: ; |
00D412D2   .E8 BD080000   call <jmp.&MSVCR100.memset>            ; \memset
00D412D7   .8B1D 9C20D400 mov ebx,dword ptr ds:[<&MSVCR100.printf>>;MSVCR100.printf
00D412DD   .68 B821D400   push 5ba358a4.00D421B8                   ; /input flag:\n
00D412E2   .FFD3          call ebx                                 ; \printf
00D412E4   .8D55 C8       lea edx,dword ptr ss:
00D412E7   .52            push edx
00D412E8   .68 C821D400   push 5ba358a4.00D421C8                   ; /%50s
00D412ED   .FF15 A420D400 call dword ptr ds:[<&MSVCR100.scanf>]    ; \scanf
00D412F3   .83C4 24       add esp,24
00D412F6   .50            push eax
00D412F7   .33C0          xor eax,eax
00D412F9   .74 03         je short 5ba358a4.00D412FE
00D412FB   .83C4 1E       add esp,1E
00D412FE   >58            pop eax
00D412FF   .8D45 C8       lea eax,dword ptr ss:            ;ascii
00D41302   .8D50 01       lea edx,dword ptr ds:             ;ascii
00D41305   >8A08          mov cl,byte ptr ds:
00D41307   .40            inc eax
00D41308   .84C9          test cl,cl
00D4130A   .^ 75 F9         jnz short 5ba358a4.00D41305
00D4130C   .2BC2          sub eax,edx                              ;上面就是计算长度
00D4130E   .83F8 21       cmp eax,21                               ;21
00D41311   .75 7D         jnz short 5ba358a4.00D41390
00D41313   .8D45 C8       lea eax,dword ptr ss:
00D41316   .E8 45FEFFFF   call 5ba358a4.00D41160                   ;第一个加密
00D4131B   .8BF0          mov esi,eax
00D4131D   .8D85 C8FEFFFF lea eax,dword ptr ss:
00D41323   .8D50 01       lea edx,dword ptr ds:
00D41326   >8A08          mov cl,byte ptr ds:
00D41328   .40            inc eax
00D41329   .84C9          test cl,cl
00D4132B   .^ 75 F9         jnz short 5ba358a4.00D41326
00D4132D   .2BC2          sub eax,edx
00D4132F   .50            push eax
00D41330   .8D85 C8FEFFFF lea eax,dword ptr ss:
00D41336   .50            push eax
00D41337   .8DBD C8FDFFFF lea edi,dword ptr ss:
00D4133D   .E8 BEFCFFFF   call 5ba358a4.00D41000
00D41342   .8BC6          mov eax,esi
00D41344   .83C4 08       add esp,8
00D41347   .8D50 01       lea edx,dword ptr ds:
00D4134A   .8D9B 00000000 lea ebx,dword ptr ds:
00D41350   >8A08          mov cl,byte ptr ds:
00D41352   .40            inc eax
00D41353   .84C9          test cl,cl
00D41355   .^ 75 F9         jnz short 5ba358a4.00D41350
00D41357   .2BC2          sub eax,edx
00D41359   .50            push eax                                 ; /Arg2
00D4135A   .56            push esi                                 ; |Arg1
00D4135B   .8D85 C8FDFFFF lea eax,dword ptr ss:         ; |
00D41361   .E8 7AFDFFFF   call 5ba358a4.00D410E0                   ; \5ba358a4.00D410E0
00D41366   .83C4 08       add esp,8
00D41369   .33C0          xor eax,eax
00D4136B   .81EE 0421D400 sub esi,5ba358a4.00D42104
00D41371   >8A8C06 0421D4>mov cl,byte ptr ds:
00D41378   .3A88 0421D400 cmp cl,byte ptr ds:
00D4137E      75 23         jnz short 5ba358a4.00D413A3
00D41380   .40            inc eax
00D41381   .83F8 2C       cmp eax,2C
00D41384   .^ 7C EB         jl short 5ba358a4.00D41371
00D41386   .68 7C21D400   push 5ba358a4.00D4217C                   ;Congratulation!!!!!!\n
00D4138B   .FFD3          call ebx
00D4138D   .83C4 04       add esp,4
00D41390   >8B4D FC       mov ecx,dword ptr ss:
00D41393   .5F            pop edi
00D41394   .5E            pop esi
00D41395   .33CD          xor ecx,ebp
00D41397   .33C0          xor eax,eax
00D41399   .5B            pop ebx
00D4139A   .E8 0D000000   call 5ba358a4.00D413AC
00D4139F   .8BE5          mov esp,ebp
00D413A1   .5D            pop ebp



00D4130E   .83F8 21       cmp eax,21                               ;21


判断输入字符长度
长度为0x21

分析了下

这个程序有两层加密
第一层在00D41316   .E8 45FEFFFF   call 5ba358a4.00D41160                   ;第一个加密
主要是把输入字符串按照里面的字母表替换
第二层在00D41361   .E8 7AFDFFFF   call 5ba358a4.00D410E0                   ; \5ba358a4.00D410E0
主要是对替换过后的字符进行异或加密

最后再跟一串字符比较 如果全部相等就输出成功字符
00D41366   .83C4 08       add esp,8
00D41369   .33C0          xor eax,eax
00D4136B   .81EE 0421D400 sub esi,5ba358a4.00D42104
00D41371   >8A8C06 0421D4>mov cl,byte ptr ds:
00D41378   .3A88 0421D400 cmp cl,byte ptr ds:
00D4137E      75 23         jnz short 5ba358a4.00D413A3
00D41380   .40            inc eax
00D41381   .83F8 2C       cmp eax,2C
00D41384   .^ 7C EB         jl short 5ba358a4.00D41371
00D41386   .68 7C21D400   push 5ba358a4.00D4217C                   ;Congratulation!!!!!!\n
00D4138B   .FFD3          call ebx



先把最后比较的字符提取出来 然后用逆着写脚本解密这串字符
20 C3 1A AE 97 3C 7A 41 DE F6 78 15 CB 4B 4C DC 26 55 8B 55 E5 E9 55 75 40 3D 82 13 A5 60 13 3B F5 D8 19 0E 47 CF 5F 5E DE 9D 14 BD


然后分析第二层加密
00D410E0/$55            push ebp
00D410E1|.8BEC          mov ebp,esp
00D410E3|.56            push esi
00D410E4|.57            push edi
00D410E5|.33C9          xor ecx,ecx
00D410E7|.33F6          xor esi,esi
00D410E9|.33FF          xor edi,edi
00D410EB|.394D 0C       cmp ,ecx
00D410EE|.76 5E         jbe short 5ba358a4.00D4114E
00D410F0|.53            push ebx
00D410F1|>41            /inc ecx                                 ;v5
00D410F2|.81E1 FF000080 |and ecx,800000FF                        ;v3 = (v3 + 1) % 256;
00D410F8|.79 08         |jns short 5ba358a4.00D41102
00D410FA|.49            |dec ecx
00D410FB|.81C9 00FFFFFF |or ecx,FFFFFF00
00D41101|.41            |inc ecx
00D41102|>8A1401      |mov dl,byte ptr ds:            ;ff740*(_BYTE *)(v3 + result);
00D41105|.0FB6DA      |movzx ebx,dl
00D41108|.03F3          |add esi,ebx                           ;v6 + v4)
00D4110A|.81E6 FF000080 |and esi,800000FF                        ;v4 = (v6 + v4) % 256;
00D41110|.79 08         |jns short 5ba358a4.00D4111A
00D41112|.4E            |dec esi
00D41113|.81CE 00FFFFFF |or esi,FFFFFF00
00D41119|.46            |inc esi
00D4111A|>0FB61C06      |movzx ebx,byte ptr ds:         ;*(_BYTE *)(v4 + result);
00D4111E|.881C01      |mov byte ptr ds:,bl            ;*(_BYTE *)(v3 + result) = *(_BYTE *)(v4 + result);
00D41121|.881406      |mov byte ptr ds:,dl            ;   *(_BYTE *)(v4 + result) = v6;
00D41124|.0FB61C01      |movzx ebx,byte ptr ds:         ;(v3 + result))
00D41128|.0FB6D2      |movzx edx,dl
00D4112B|.03DA          |add ebx,edx                           ;v6 + *(unsigned __int8 *)(v3 + result)
00D4112D|.81E3 FF000080 |and ebx,800000FF                        ;v6 + *(unsigned __int8 *)(v3 + result)) % 256
00D41133|.79 08         |jns short 5ba358a4.00D4113D
00D41135|.4B            |dec ebx
00D41136|.81CB 00FFFFFF |or ebx,FFFFFF00
00D4113C|.43            |inc ebx
00D4113D|>0FB61C03      |movzx ebx,byte ptr ds:         ;*(_BYTE *)((v6 + *(unsigned __int8 *)(v3 + result)) % 256 + result);
00D41141|.8B55 08       |mov edx,
00D41144|.301C17      |xor byte ptr ds:,bl            ;7a a6 6a
00D41147|.47            |inc edi
00D41148|.3B7D 0C       |cmp edi,
00D4114B|.^ 72 A4         \jb short 5ba358a4.00D410F1
00D4114D|.5B            pop ebx
00D4114E|>5F            pop edi
00D4114F|.5E            pop esi
00D41150|.5D            pop ebp
00D41151\.C3            retn


这段程序主要是经过乱七八糟的运算 然后根据运算取出内存中的值用来跟输入的字符异或

这就表示 取出内存中的值是不会变的

这段加密程序的话有点复杂 写脚本解密花的时间也有点多
主要看关键点
00D4113D|> \0FB61C03      |movzx ebx,byte ptr ds:         ;提取内存中的数据
00D41141|.8B55 08       |mov edx,
00D41144|.301C17      |xor byte ptr ds:,bl            ;跟字符串异或加密

这个时候只要不断摁f4把内存中的数据提取出来就行
7a a6 6a da cd 0f 16 74 8b be 29 67 aa 79 79 b2 42 64 b2 2c bc 93 18 07 19 6f b7 64 fd 52 59 4f 96 ea 49 3c 11 89 66 39 87 d3 59 84

然后用python写脚本解密
key = '7a a6 6a da cd 0f 16 74 8b be 29 67 aa 79 79 b2 42 64 b2 2c bc 93 18 07 19 6f b7 64 fd 52 59 4f 96 ea 49 3c 11 89 66 39 87 d3 59 84'
en_flag = '20 C3 1A AE 97 3C 7A 41 DE F6 78 15 CB 4B 4C DC 26 55 8B 55 E5 E9 55 75 40 3D 82 13 A5 60 13 3B F5 D8 19 0E 47 CF 5F 5E DE 9D 14 BD'
key = key.split(' ')
en_flag = en_flag.split(' ')
en_flags = []
keys = []

g = ''
for i in key:
      keys.append(int(i, 16))
for i in en_flag:
      en_flags.append(int(i, 16))

for q in range(len(key)):
      g += chr(keys^en_flags)
print g
得到这段字符

ZeptZ3l5UHQra25nd19yYzMrYR5wX2Jtc2P2VF9gYNM9


再看第一层加密
代码篇幅有点多

我主要列出重要的
00D411DA|.8D9B 00000000 lea ebx,dword ptr ds:
00D411E0|>6A 03         /push 3                                  ; /maxlen = 3
00D411E2|.8D55 F8       |lea edx,                     ; |
00D411E5|.53            |push ebx                              ; |src
00D411E6|.33FF          |xor edi,edi                           ; |
00D411E8|.52            |push edx                              ; |dest
00D411E9|.897D F8       |mov ,edi                     ; |
00D411EC|.FF15 A020D400 |call dword ptr ds:[<&MSVCR100.strncpy>] ; \strncpy
00D411F2|.8D4D F8       |lea ecx,                     ;_is
00D411F5|.83C4 0C       |add esp,0C
00D411F8|.33C0          |xor eax,eax
00D411FA|.8D71 01       |lea esi,dword ptr ds:
00D411FD|.8D49 00       |lea ecx,dword ptr ds:
00D41200|>8A11          |/mov dl,byte ptr ds:               ;_
00D41202|.41            ||inc ecx
00D41203|.84D2          ||test dl,dl
00D41205|.^ 75 F9         |\jnz short 5ba358a4.00D41200
00D41207|.2BCE          |sub ecx,esi
00D41209|.8BD1          |mov edx,ecx
00D4120B|.74 16         |je short 5ba358a4.00D41223
00D4120D|.B9 10000000   |mov ecx,10
00D41212|>0FBE7405 F8   |/movsx esi,byte ptr ss:      ;_
00D41217|.D3E6          ||shl esi,cl                           ;10 69 00
00D41219|.40            ||inc eax                              ;740000 5F00 74
00D4121A|.83E9 08       ||sub ecx,8
00D4121D|.0BFE          ||or edi,esi
00D4121F|.3BC2          ||cmp eax,edx
00D41221|.^ 72 EF         |\jb short 5ba358a4.00D41212
00D41223|>33C0          |xor eax,eax
00D41225|.8D72 01       |lea esi,dword ptr ds:            ;04
00D41228|.8D48 12       |lea ecx,dword ptr ds:         ;12
00D4122B|.EB 03         |jmp short 5ba358a4.00D41230
00D4122D|   8D49 00       |lea ecx,dword ptr ds:
00D41230|>3BF0          |/cmp esi,eax
00D41232|.76 15         ||jbe short 5ba358a4.00D41249
00D41234|.8B5D FC       ||mov ebx,
00D41237|.8BD7          ||mov edx,edi
00D41239|.D3FA          ||sar edx,cl                           ;   12 0C 06 00
00D4123B|.83E2 3F       ||and edx,3F
00D4123E|.8A92 3821D400 ||mov dl,byte ptr ds:      ;主要是这两步
00D41244|.881403      ||mov byte ptr ds:,dl
00D41247|.EB 07         ||jmp short 5ba358a4.00D41250
00D41249|>8B55 FC       ||mov edx,
00D4124C|.C60402 3D   ||mov byte ptr ds:,3D
00D41250|>83E9 06       ||sub ecx,6
00D41253|.40            ||inc eax
00D41254|.83F9 FA       ||cmp ecx,-6
00D41257|.^ 7F D7         |\jg short 5ba358a4.00D41230
00D41259|.8B5D F0       |mov ebx,
00D4125C|.8345 FC 04    |add ,4
00D41260|.83C3 03       |add ebx,3
00D41263|.FF4D EC       |dec
00D41266|.895D F0       |mov ,ebx
00D41269|.^ 0F85 71FFFFFF \jnz 5ba358a4.00D411E0
00D4126F|>8B45 F4       mov eax,
00D41272|.5F            pop edi
00D41273|.5E            pop esi
00D41274|.5B            pop ebx
00D41275|.8BE5          mov esp,ebp
00D41277|.5D            pop ebp
00D41278\.C3            retn

主要思路是
循环strlen(input)/3次
一开始会把输入字符串复制到另一块内存区域 长度为3
00D411E0|> /6A 03         /push 3                                  ; /maxlen = 3
00D411E2|. |8D55 F8       |lea edx,                     ; |
00D411E5|. |53            |push ebx                              ; |src
00D411E6|. |33FF          |xor edi,edi                           ; |
00D411E8|. |52            |push edx                              ; |dest
00D411E9|. |897D F8       |mov ,edi                     ; |
00D411EC|. |FF15 A020D400 |call dword ptr ds:[<&MSVCR100.strncpy>] ; \strncpy


然后会把输入字符 换成ascii码 左移第一个字符左移四位(16进制下) 第二个字符左移两位最后一个字符不左移 再相加起来
比如fla最后会变成00666C61
00D41212|> /0FBE7405 F8   |/movsx esi,byte ptr ss:                      ;_
00D41217|. |D3E6          ||shl esi,cl                                             ;
00D41219|. |40            ||inc eax                                                ;
00D4121A|. |83E9 08       ||sub ecx,8
00D4121D|. |0BFE          ||or edi,esi
00D4121F|. |3BC2          ||cmp eax,edx
00D41221|.^\72 EF         |\jb short 5ba358a4.00D41212



在最后 得到的数值00666C61右移后 使用and保留最后6位(二进制下)
循环四次 第一次右移移动了18位(2进制)
第二次右移移动了12位
第三次右移移动了6位
最后一次不右移
00666C61 转成2进制是24位的
and 0x3f 只保留最低6位
所以 四次 恰好能保存 这个24位的数值(00666C61)
然后在用经过加密后的数值+D42138 后当做地址取出里面的值
看了下内容 是个字母表ABCDEFGHIJSTUVWK
LMNOPQRXYZabcdqr
stuvwxefghijklmn
opyz0123456789+
附上代码
00D41230|>3BF0          |/cmp esi,eax
00D41232|. |76 15         ||jbe short 5ba358a4.00D41249
00D41234|. |8B5D FC       ||mov ebx,
00D41237|. |8BD7          ||mov edx,edi
00D41239|. |D3FA          ||sar edx,cl                                             ;   12 0C 06 00
00D4123B|. |83E2 3F       ||and edx,3F
00D4123E|. |8A92 3821D400 ||mov dl,byte ptr ds:                        ;主要是这两步
00D41244|. |881403      ||mov byte ptr ds:,dl
00D41247|. |EB 07         ||jmp short 5ba358a4.00D41250
00D41249|> |8B55 FC       ||mov edx,
00D4124C|. |C60402 3D   ||mov byte ptr ds:,3D
00D41250|> |83E9 06       ||sub ecx,6
00D41253|. |40            ||inc eax
00D41254|. |83F9 FA       ||cmp ecx,-6
00D41257|.^\7F D7         |\jg short 5ba358a4.00D41230
00D41259|.8B5D F0       |mov ebx,
00D4125C|.8345 FC 04    |add ,4
00D41260|.83C3 03       |add ebx,3
00D41263|.FF4D EC       |dec
00D41266|.895D F0       |mov ,ebx
00D41269|.^ 0F85 71FFFFFF \jnz 5ba358a4.00D411E0




到了这里 这层加密的主要思路是 主循环循环len(input)/3 次

先复制内容到另一段内存长度为三
然后取出字符左移储存
在循环四次每次把数值右移 在进行and 0x3f截断数值
最后得到这个数值+D42138 取出字母当做密文
最后得到
ZeptZ3l5UHQra25nd19yYzMrYR5wX2Jtc2P2VF9gYNM9
可以根据这段密文解密

直接上脚本 用C写比较方便一些
#include <stdio.h>


int main()
{
    char asciis = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'S', 'T', 'U', 'V', 'W', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    char encrypt = {'Z', 'e', 'p', 't', 'Z', '3', 'l', '5', 'U', 'H', 'Q', 'r', 'a', '2', '5', 'n', 'd', '1', '9', 'y', 'Y', 'z', 'M', 'r', 'Y', 'R', '5', 'w', 'X', '2', 'J', 't', 'c', '2', 'P', '2', 'V', 'F', '9', 'g', 'Y', 'N', 'M', '9'};
    int base;
    int flag;

    for(int i=43; i>=0; i=i-4)
    {
      base = i;
      base = i-1;
      base = i-2;
      base = i-3;
      //下面找出字母在字母表中对应的位置
      flag = 0;
      flag = 0;
      flag = 0;
      flag = 0;
      for(int count=3; count>=0; --count)
      {
            for(int counts=0; counts<62; counts++)
            {
                if(encrypt] == asciis)
                {
                  flag = counts;
                  break;
                }
            }
      }
      flag = flag * 0x40;
      flag = flag * 0x1000;
      flag = flag * 0x40000;
      printf("%x\n", flag+flag+flag+flag);

    }


    return 0;
}


好了 可以看到下面的字符 是fla这些数字是16进制的

可以用python写脚本输出
i = '666c61677b7930755f6b6e6f775f7263345f616e645f6261736536345f6861247d'
jjj = ''

for j in range(0, len(i), 2):
      jjj += chr(int(i, 16))

print jjj




写得比较匆忙望见谅
果然还是自己太菜了 写解密脚本拖了好久

这个flag提到 base64和 rc4是不是还有更快的解法 希望有能力的大佬给看看

剑残雪飘 发表于 2018-9-23 22:22

yechen123 发表于 2018-9-23 22:07
22号的安恒杯月赛,不是很懂那些加密算法识别,所以只能硬着头皮反汇编一步一步分解,还是得多看看识别算 ...

这个程序比较简陋,算法也很常见,出题人还耍小聪明

栈平衡一下就行了,不过也没啥用 main函数处理的也很简洁



一步一步调也能做,反正结果是异或出来的,把中间过程生成用来异或的值拿出来,跟 要结果异或一下就行了。

zhukai055 发表于 2018-9-23 09:44

第一个call base64加密(改了密码表)
第二个call rc4 第一步:生成密码表
第三个call rc4 第二步:加密()

iamafailor 发表于 2018-9-22 23:28

大神都说自己菜 我们菜鸟怎么办

sphinx-diss 发表于 2018-9-22 23:52

旁观者看看热闹            {:1_925:}

姚小宝 发表于 2018-9-22 23:55

sphinx-diss 发表于 2018-9-22 23:52
旁观者看看热闹

咋了。。。。

sphinx-diss 发表于 2018-9-23 00:00

yechen123 发表于 2018-9-22 23:55
咋了。。。。

顶你上去老铁咱只是个门外汉 不懂你们这些代码

holiness 发表于 2018-9-23 08:14

感谢楼主分享,支持一下!

LjeA 发表于 2018-9-23 08:41

看我一脸茫然,目前学术不高,等我提高我会回来回顾一下的

cxb2468 发表于 2018-9-23 09:16


感谢楼主分享,支持一下!

姚小宝 发表于 2018-9-23 09:59

zhukai055 发表于 2018-9-23 09:44
第一个call base64加密(改了密码表)
第二个call rc4 第一步:生成密码表
第三个call rc4 第二步:加密 ...

多谢指点{:1_893:}{:1_893:}
页: [1] 2 3 4 5 6 7 8
查看完整版本: 九月份安恒杯月赛之NewDriver