首页
社区
课程
招聘
[原创]网络安全大赛之Key-enc
发表于: 2013-9-25 21:28 15327

[原创]网络安全大赛之Key-enc

2013-9-25 21:28
15327

这是一个信安比赛的题目,有兴趣的可以拿来练练手,题目如下:

key.txt的内容为:NDE4OUM3MUVBNUZFOTFBM0NCRUI5OTcyMDUzN0VBNEIzMjIxRUIxNDhCOTU3Mzcw=
好,现在开始逆向该程序
运行后,界面如下:


这里,原始数据输入12345678,然后加密文本


这个提示很关键,得到的密文在encrypted.txt中,密文为:MDhGMkQ5RDA0RTU2MzY3NkRFRDRCQUFCODREMjU0OTY=
使用IDA搜索字符串,即可得到调用这个字符串的位置。然后找到这个位置的函数头,在407AB0处设断,用OD载入运行。
.text:00407AB0                 push    ebp
.text:00407AB1                 mov     ebp, esp
.text:00407AB3                 push    0FFFFFFFFh
.text:00407AB5                 push    offset SEH_407AB0
当点击加密文本,就会在断点处停下。说明断点没有问题,但是这个函数里面有大量的函数调用,要是一个个分析还是挺繁琐的。所以当我运行到某个函数调用时我会想用IDA看看子函数的功能,考虑要不要进入。关键是要找个与自己输入数据有关的算法即可。
00407AE4  |.  59            pop ecx
00407AE5  |.  894D F0       mov [local.4],ecx
00407AE8  |.  6A 01         push 0x1
00407AEA  |.  8B4D F0       mov ecx,[local.4]
00407AED  |.  E8 89CA0800   call Key-enc.0049457B
00407AF2  |.  8B4D F0       mov ecx,[local.4]
00407AF5  |.  83C1 5C       add ecx,0x5C                                        ;输入数据的偏移
00407AF8  |.  E8 63A60D00   call Key-enc.004E2160                    ;  关键函数 判断输入数据长度
00407AFD  |.  85C0          test eax,eax                    
00407AFF  |.  7F 13         jg XKey-enc.00407B14                                ;若输入数据为0则结束
00407B01  |.  6A 00         push 0x0
00407B03  |.  6A 00         push 0x0
00407B05  |.  68 B8D55C00   push Key-enc.005CD5B8                    ;  加密数据不能为空!
00407B0A  |.  E8 12C80A00   call Key-enc.004B4321
00407B0F  |.  E9 32020000   jmp Key-enc.00407D46
00407B14  |>  8D4D EC       lea ecx,[local.5]                        ;  18f630
00407B17  |.  E8 A097FFFF   call Key-enc.004012BC                    ;  将5cd01c写入18f630
00407B1C  |.  C745 FC 00000>mov [local.1],0x0
00407B23  |.  8D4D DC       lea ecx,[local.9]                        ;  18f620
00407B26  |.  E8 A795FFFF   call Key-enc.004010D2                    ;  将5cd094写入18f620
00407B2B  |.  C645 FC 01    mov byte ptr ss:[ebp-0x4],0x1
00407B2F  |.  8D45 DC       lea eax,[local.9]
00407B32  |.  50            push eax                                 ;  18f620
00407B33  |.  E8 3596FFFF   call Key-enc.0040116D                    ;  获取关键信息到 [18f620+0c]
00407B38  |.  83C4 04       add esp,0x4
00407B3B  |.  8D4D DC       lea ecx,[local.9]
00407B3E  |.  E8 EF94FFFF   call Key-enc.00401032                    ;  关键函数这里会进行一些算法的转换,但与输入数据无关
为了节省时间 若后来用的到只需用其结果即可。
00407B43  |.  8D4D DC       lea ecx,[local.9]
00407B46  |.  E8 E695FFFF   call Key-enc.00401131                    ;  [18f620+0c]处的数据会变
00407B4B  |.  8D4D CC       lea ecx,[local.13]                       ;  18f610
00407B4E  |.  E8 7F95FFFF   call Key-enc.004010D2                    ;  将5cd094写入ecx
00407B53  |.  C645 FC 02    mov byte ptr ss:[ebp-0x4],0x2
00407B57  |.  8D4D CC       lea ecx,[local.13]
00407B5A  |.  51            push ecx
00407B5B  |.  8B4D F0       mov ecx,[local.4]
00407B5E  |.  83C1 5C       add ecx,0x5C                             ;  终于看到输入数据啦嘿嘿
00407B61  |.  E8 FAA50D00   call Key-enc.004E2160
00407B66  |.  50            push eax                                 ;  size
00407B67  |.  8B4D F0       mov ecx,[local.4]
00407B6A  |.  83C1 5C       add ecx,0x5C                             ;  buffer
00407B6D  |.  E8 38A60D00   call Key-enc.004E21AA
00407B72  |.  50            push eax                                 ;  输入数据的buffer
00407B73  |.  8D4D DC       lea ecx,[local.9]
00407B76  |.  E8 5F97FFFF   call Key-enc.004012DA
00407B7B  |.  50            push eax                                 ;  size2
00407B7C  |.  8D4D DC       lea ecx,[local.9]
00407B7F  |.  E8 7096FFFF   call Key-enc.004011F4
00407B84  |.  50            push eax                                 ;  相关数据的buffer
00407B85  |.  E8 7E96FFFF   call Key-enc.00401208                   ;  关键函数 变第一次
这个函数应该比较关键 有5个压栈参数这里有输入数据的偏移,大小,关键信息的偏移,大小,和一个地址,在函数返回后即算法结束后得到的结果应该与该地址有关
这里的地址为18f610,在18f610+c的地方存的就是数据的地址
0018F610   005CD094  斝\.   Key-enc.005CD094
0018F614   00000008  ...
0018F618   00000801  ..
0018F61C   02127798  榳
 
02127798  92 A8 01 86 FB BA 80 4B 00 00 00 00 00 00 00 00  挩嘂簚K........
这个数据应该就是进行第一次算法变换后得到的数据,然后就密切关注该数据怎么样变化才能得到最终的密文,这是我是先找关键地方的代码,最后再分析具体流程,上面红色字就会第一次关键变换。
接着分析主函数:
00407B85  |.  E8 7E96FFFF   call Key-enc.00401208                    ;  关键函数 变一次
00407B8A  |.  83C4 14       add esp,0x14
00407B8D  |.  8D4D CC       lea ecx,[local.13]
00407B90  |.  E8 9D94FFFF   call Key-enc.00401032                    ;  关键函数 变第二次 kqgBhvu6gEs=
这里的地址用ecx传的,还是为18f610 在18f610+c处存的地址有变化
0018F610   005CD094  斝\.   Key-enc.005CD094
0018F614   0000000C  ....
0018F618   00000801  ..
0018F61C   02126728  (g  ASCII "kqgBhvu6gEs="
 
02126728  6B 71 67 42 68 76 75 36 67 45 73 3D 00 00 00 00  kqgBhvu6gEs=....
这个数据应该就是进行第二次算法变换后得到的数据,然后就密切关注该数据怎么样变化才能得到最终的密文。
接着分析主函数 这里也有很多函数调用,可以用IDA分析具体功能,一下是我自己分析的一些作用的标注
00407B95  |.  8D4D C8       lea ecx,[local.14]
00407B98  |.  E8 FC96FFFF   call Key-enc.00401299
00407B9D  |.  C645 FC 03    mov byte ptr ss:[ebp-0x4],0x3
00407BA1  |.  8D4D B8       lea ecx,[local.18]
00407BA4  |.  E8 2995FFFF   call Key-enc.004010D2                    ;  18f5fc 不用跟进
00407BA9  |.  C645 FC 04    mov byte ptr ss:[ebp-0x4],0x4
00407BAD  |.  8D55 B8       lea edx,[local.18]
00407BB0  |.  52            push edx
00407BB1  |.  E8 C096FFFF   call Key-enc.00401276
00407BB6  |.  83C4 04       add esp,0x4
00407BB9  |.  8D4D B8       lea ecx,[local.18]
00407BBC  |.  E8 7095FFFF   call Key-enc.00401131                    ;  [18f5fc+0x0c]的数据与输入无关
00407BC1  |.  8D4D A8       lea ecx,[local.22]
00407BC4  |.  E8 0995FFFF   call Key-enc.004010D2
00407BC9  |.  C645 FC 05    mov byte ptr ss:[ebp-0x4],0x5            ;  18f5ec 不用跟进
00407BCD  |.  8D45 A8       lea eax,[local.22]
00407BD0  |.  50            push eax
00407BD1  |.  8D4D CC       lea ecx,[local.13]
00407BD4  |.  E8 0197FFFF   call Key-enc.004012DA                    ;  取[18f610+0x0c]数据的长度
00407BD9  |.  50            push eax
00407BDA  |.  8D4D CC       lea ecx,[local.13]
00407BDD  |.  E8 1296FFFF   call Key-enc.004011F4                    ;  不用管
00407BE2  |.  50            push eax
00407BE3  |.  8D4D B8       lea ecx,[local.18]
00407BE6  |.  E8 EF96FFFF   call Key-enc.004012DA
00407BEB  |.  50            push eax                                 ;  [18f5fc+0x0c]的数据长度
00407BEC  |.  8D4D B8       lea ecx,[local.18]
00407BEF  |.  E8 0096FFFF   call Key-enc.004011F4
00407BF4  |.  50            push eax
00407BF5  |.  E8 0E96FFFF   call Key-enc.00401208                    ;  关键函数 第三次变
这个函数和第一个关键函数一样 有5个压栈参数这里有输入数据的偏移,大小,关键信息的偏移,大小,和一个地址,在函数返回后即算法结束后得到的结果应该与该地址有关
这里的地址为18f5ec,在18f5ec+c的地方存的就是数据的地址
0018F5EC   005CD094  斝\.   Key-enc.005CD094
0018F5F0   00000010  ...
0018F5F4   00000801  ..
0018F5F8   02128808  ?
 
02128808  08 F2 D9 D0 4E 56 36 76 DE D4 BA AB 84 D2 54 96  蛸蠳V6v拊韩勔T?
这个数据应该就是进行第三次算法变换后得到的数据,然后就密切关注该数据怎么样变化才能得到最终的密文 
 
接着分析主函数:
00407BFA  |.  83C4 14       add esp,0x14
00407BFD  |.  8D4D A8       lea ecx,[local.22]
00407C00  |.  E8 0094FFFF   call Key-enc.00401005                    ;  要进去 第四次
这里有ecx传参数 为18f5ec,运行后,
这里的地址为18f5ec,在18f5ec+c的地方存的就是数据的地址
0018F5EC   005CD094  斝\.   Key-enc.005CD094
0018F5F0   00000020   ...
0018F5F4   00000800  ...
0018F5F8   02127798  榳   ASCII "08F2D9D04E563676DED4BAAB84D25496"
 
 
02127798  30 38 46 32 44 39 44 30 34 45 35 36 33 36 37 36  08F2D9D04E563676
021277A8  44 45 44 34 42 41 41 42 38 34 44 32 35 34 39 36  DED4BAAB84D25496
这个数据应该就是进行第四次算法变换后得到的数据 不过这功能很明显,和第三次算法后得到的数据对比 即可知晓。
 然后就密切关注该数据怎么样变化才能得到最终的密文
接着分心主函数:
00407C05  |.  8D4D A8       lea ecx,[local.22]
00407C08  |.  E8 2594FFFF   call Key-enc.00401032                    ;  关键函数 第五次
00407C0D  |.  8D4D 98       lea ecx,[local.26]                       ;  最终数据已经出来了
这里有ecx传参数 为18f5ec,运行后,
这里的地址为18f5ec,在18f5ec+c的地方存的就是数据的地址
0018F5EC   005CD094  斝\.   Key-enc.005CD094
0018F5F0   0000002C  ,...
0018F5F4   00000801  ..
0018F5F8   00227798  榳".   ASCII "MDhGMkQ5RDA0RTU2MzY3NkRFRDRCQUFCODREMjU0OTY="
 
00227798  4D 44 68 47 4D 6B 51 35 52 44 41 30 52 54 55 32  MDhGMkQ5RDA0RTU2
002277A8  4D 7A 59 33 4E 6B 52 46 52 44 52 43 51 55 46 43  MzY3NkRFRDRCQUFC
002277B8  4F 44 52 45 4D 6A 55 30 4F 54 59 3D              ODREMjU0OTY=
这是第五次变换得到的数据也就是最终数据。
所以主要就是这5个关键的变换函数,会发现第一次和第三次函数为同一个,第二次与第第五次函数为同一个,第四次的功能很明显就不需要分析了。
 
接着先分析函数00401208
函数进入以后,还是有很多功能调用,用IDA分析,最关键的是下面一个函数调用:

用IDA进入分析,有三个关键函数,40D1D0,40D880,40D310 其他函数有时间也可以分析下如果有时间的话,很多应该是迷惑我们的,这里可以设将输入的数据内存断点 分析也会跳到第一个函数里面,不过期间程序又将数据转存了的,所以内存断点的位置也应该变
第一个函数应该是将输入的数据以4个位单位倒叙 每次倒叙8个字节 得到如下,这也是函数2的一个参数
0018F278  34 33 32 31 38 37 36 35                          43218765
函数2的第二个参数是18f2f0,从下面看函数二调用了三次,每次的第一个参数为18f278,第二个参数分别为18f2f0,18f370,18f3f0
0040D094  |.  50            |push eax                                ;  18f2f0  这三个函数最关键
0040D095  |.  8D4D F0       |lea ecx,[local.4]
0040D098  |.  51            |push ecx
0040D099  |.  E8 E2070000   |call Key-enc.0040D880                   ;  跟进
0040D09E  |.  83C4 08       |add esp,0x8
0040D0A1  |.  8B55 08       |mov edx,[arg.1]
0040D0A4  |.  81C2 80000000 |add edx,0x80
0040D0AA  |.  52            |push edx                                ;  18f370
0040D0AB  |.  8D45 F0       |lea eax,[local.4]
0040D0AE  |.  50            |push eax
0040D0AF  |.  E8 CC070000   |call Key-enc.0040D880                   ;  同上
0040D0B4  |.  83C4 08       |add esp,0x8
0040D0B7  |.  8B4D 08       |mov ecx,[arg.1]
0040D0BA  |.  81C1 00010000 |add ecx,0x100
0040D0C0  |.  51            |push ecx                                ;  18f3f0
0040D0C1  |.  8D55 F0       |lea edx,[local.4]
0040D0C4  |.  52            |push edx
0040D0C5  |.  E8 B6070000   |call Key-enc.0040D880                   ;  同上
这三个地方存的数据为(第二次调用本函数时这个地方的值会不同,不过都与输入数据无关):
0018F2F0  29 32 33 38 01 06 06 09 22 1C 19 34 21 18 32 03  )238."4!2
0018F300  30 20 39 39 1F 20 34 0D 0E 03 0D 31 14 33 06 2F  0 99 4..13/
0018F310  07 0C 1D 0A 21 14 33 2D 20 10 05 3B 07 28 2B 15  ..!3- ;(+
0018F320  16 31 0F 28 1C 22 19 3C 0F 0A 2E 07 09 11 13 15  1("<...
0018F330  19 1B 2D 0F 20 22 08 34 25 0E 26 02 0E 0C 1D 27  - "4%&.'
0018F340  12 01 35 07 12 0D 1D 12 11 33 32 11 21 12 29 36  5.32!)6
0018F350  29 2A 36 36 08 2C 24 3A 1C 04 3A 36 16 0D 0B 0A  )*66,$::6. .
0018F360  12 27 18 1C 20 10 2E 1B 0B 00 3A 2C 34 17 2C 0B  ' . .:,4, 
 
0018F370  1F 15 00 28 20 10 26 1B 0D 23 1A 3A 0A 10 20 0B  .( &.#:. 
0018F380  14 3D 38 34 12 30 22 32 28 08 32 21 13 2E 25 0A  =840"2(2!.%.
0018F390  27 2A 24 10 21 06 3C 12 12 07 30 06 24 23 0D 04  '*$!<0$#.
0018F3A0  18 04 07 0E 0F 0D 0C 22 0B 3E 22 07 08 18 0A 35  .." >".5
0018F3B0  09 30 24 2E 11 19 19 14 27 25 07 02 18 10 2B 24  .0$.'%+$
0018F3C0  2C 11 05 0B 36 24 08 3D 20 2A 09 13 23 25 17 25  , 6$= *.#%%
0018F3D0  16 0A 1D 21 29 13 10 29 12 10 08 3D 1C 2F 30 07  .!))=/0
0018F3E0  21 16 3B 28 0D 08 32 00 09 15 19 34 04 0F 0E 09  !;(.2..4.
 
0018F3F0  32 3D 12 3C 1C 0E 2C 0B 30 20 32 24 0D 3B 26 0B  2=<, 0 2$.;& 
0018F400  1E 3A 39 3C 30 23 32 02 2C 0E 18 39 2F 14 24 0F  :9<0#2,9/$
0018F410  22 15 1D 30 12 25 16 29 05 31 09 1B 3D 12 33 0D  "0%)1.=3.
0018F420  2B 28 05 29 08 3B 2A 3D 1C 1C 0F 2A 37 09 13 24  +();*=*7.$
0018F430  04 2F 09 0F 0C 2D 13 35 1F 00 27 0B 26 07 08 35  /..-5.' &5
0018F440  22 3F 07 06 21 0A 1D 26 39 38 34 07 1B 24 19 14  "?!.&984$
0018F450  0C 07 26 11 1A 3B 2D 32 15 2D 32 26 20 15 05 3A  .&;-2-2& :
0018F460  29 12 3A 16 26 0A 2A 12 07 14 2A 18 39 0C 2C 1A  ):&.**9.,
这应该是前面所说的关键信息经过变换得到的,当时我没有分析,因为这与输入数据无关,现在就直接用吧。 
用IDA分析函数2:
unsigned int __cdecl sub_40D880(int a1, int a2)
{
    unsigned int v2; // ecx@1
    unsigned int v3; // ecx@4
    unsigned int result; // eax@4
    //char v5; // [sp+Ch] [bp-54h]@1
    int i; // [sp+4Ch] [bp-14h]@1
    unsigned int v7; // [sp+50h] [bp-10h]@1
    unsigned int v8; // [sp+54h] [bp-Ch]@1
    unsigned int v9; // [sp+58h] [bp-8h]@1
    int v10; // [sp+5Ch] [bp-4h]@3
    int v11; // [sp+6Ch] [bp+Ch]@3
    int dword_5F47B0[] = {0x80108020,0x80008000,0x00008000,0x00108020,
        0x00100000,0x00000020,0x80100020,0x80008020,
        0x80000020,0x80108020,0x80108000,0x80000000,
        0x80008000,0x00100000,0x00000020,0x80100020,
        0x00108000,0x00100020,0x80008020,0x00000000,
        0x80000000,0x00008000,0x00108020,0x80100000,
        0x00100020,0x80000020,0x00000000,0x00108000,
        0x00008020,0x80108000,0x80100000,0x00008020,
        0x00000000,0x00108020,0x80100020,0x00100000,
        0x80008020,0x80100000,0x80108000,0x00008000,
        0x80100000,0x80008000,0x00000020,0x80108020,
        0x00108020,0x00000020,0x00008000,0x80000000,
        0x00008020,0x80108000,0x00100000,0x80000020,
        0x00100020,0x80008020,0x80000020,0x00100020,
        0x00108000,0x00000000,0x80008000,0x00008020,
        0x80000000,0x80100020,0x80108020,0x00108000};
    int dword_5F49B0[] = {0x00802001,0x00002081,0x00002081,0x00000080,
        0x00802080,0x00800081,0x00800001,0x00002001,
        0x00000000,0x00802000,0x00802000,0x00802081,
        0x00000081,0x00000000,0x00800080,0x00800001,
        0x00000001,0x00002000,0x00800000,0x00802001,
        0x00000080,0x00800000,0x00002001,0x00002080,
        0x00800081,0x00000001,0x00002080,0x00800080,
        0x00002000,0x00802080,0x00802081,0x00000081,
        0x00800080,0x00800001,0x00802000,0x00802081,
        0x00000081,0x00000000,0x00000000,0x00802000,
        0x00002080,0x00800080,0x00800081,0x00000001,
        0x00802001,0x00002081,0x00002081,0x00000080,
        0x00802081,0x00000081,0x00000001,0x00002000,
        0x00800001,0x00002001,0x00802080,0x00800081,
        0x00002001,0x00002080,0x00800000,0x00802001,
        0x00000080,0x00800000,0x00002000,0x00802080};
    int dword_5F4BB0[] = {0x20000010,0x20400000,0x00004000,0x20404010
        ,0x20400000,0x00000010,0x20404010,0x00400000
        ,0x20004000,0x00404010,0x00400000,0x20000010
        ,0x00400010,0x20004000,0x20000000,0x00004010
        ,0x00000000,0x00400010,0x20004010,0x00004000
        ,0x00404000,0x20004010,0x00000010,0x20400010
        ,0x20400010,0x00000000,0x00404010,0x20404000
        ,0x00004010,0x00404000,0x20404000,0x20000000
        ,0x20004000,0x00000010,0x20400010,0x00404000
        ,0x20404010,0x00400000,0x00004010,0x20000010
        ,0x00400000,0x20004000,0x20000000,0x00004010
        ,0x20000010,0x20404010,0x00404000,0x20400000
        ,0x00404010,0x20404000,0x00000000,0x20400010
        ,0x00000010,0x00004000,0x20400000,0x00404010
        ,0x00004000,0x00400010,0x20004010,0x00000000
        ,0x20404000,0x20000000,0x00400010,0x20004010};
    int dword_5F4DB0[] = {0x10001040,0x00001000,0x00040000,0x10041040
        ,0x10000000,0x10001040,0x00000040,0x10000000
        ,0x00040040,0x10040000,0x10041040,0x00041000
        ,0x10041000,0x00041040,0x00001000,0x00000040
        ,0x10040000,0x10000040,0x10001000,0x00001040
        ,0x00041000,0x00040040,0x10040040,0x10041000
        ,0x00001040,0x00000000,0x00000000,0x10040040
        ,0x10000040,0x10001000,0x00041040,0x00040000
        ,0x00041040,0x00040000,0x10041000,0x00001000
        ,0x00000040,0x10040040,0x00001000,0x00041040
        ,0x10001000,0x00000040,0x10000040,0x10040000
        ,0x10040040,0x10000000,0x00040000,0x10001040
        ,0x00000000,0x10041040,0x00040040,0x10000040
        ,0x10040000,0x10001000,0x10001040,0x00000000
        ,0x10041040,0x00041000,0x00041000,0x00001040
        ,0x00001040,0x00040040,0x10000000,0x10041000};
    int dword_5F46B0[] = {0x01010400,0x00000000,0x00010000,0x01010404,
        0x01010004,0x00010404,0x00000004,0x00010000,
        0x00000400,0x01010400,0x01010404,0x00000400,
        0x01000404,0x01010004,0x01000000,0x00000004,
        0x00000404,0x01000400,0x01000400,0x00010400,
        0x00010400,0x01010000,0x01010000,0x01000404,
        0x00010004,0x01000004,0x01000004,0x00010004,
        0x00000000,0x00000404,0x00010404,0x01000000,
        0x00010000,0x01010404,0x00000004,0x01010000,
        0x01010400,0x01000000,0x01000000,0x00000400,
        0x01010004,0x00010000,0x00010400,0x01000004,
        0x00000400,0x00000004,0x01000404,0x00010404,
        0x01010404,0x00010004,0x01010000,0x01000404,
        0x01000004,0x00000404,0x00010404,0x01010400,
        0x00000404,0x01000400,0x01000400,0x00000000,
        0x00010004,0x00010400,0x00000000,0x01010004};
    int dword_5F48B0[] = {0x00000208,0x08020200,0x00000000,0x08020008,
        0x08000200,0x00000000,0x00020208,0x08000200,
        0x00020008,0x08000008,0x08000008,0x00020000,
        0x08020208,0x00020008,0x08020000,0x00000208,
        0x08000000,0x00000008,0x08020200,0x00000200,
        0x00020200,0x08020000,0x08020008,0x00020208,
        0x08000208,0x00020200,0x00020000,0x08000208,
        0x00000008,0x08020208,0x00000200,0x08000000,
        0x08020200,0x08000000,0x00020008,0x00000208,
        0x00020000,0x08020200,0x08000200,0x00000000,
        0x00000200,0x00020008,0x08020208,0x08000200,
        0x08000008,0x00000200,0x00000000,0x08020008,
        0x08000208,0x00020000,0x08000000,0x08020208,
        0x00000008,0x00020208,0x00020200,0x08000008,
        0x08020000,0x08000208,0x00000208,0x08020000,
        0x00020208,0x00000008,0x08020008,0x00020200};
    int dword_5F4AB0[] = {0x00000100,0x02080100,0x02080000,0x42000100,
        0x00080000,0x00000100,0x40000000,0x02080000,
        0x40080100,0x00080000,0x02000100,0x40080100,
        0x42000100,0x42080000,0x00080100,0x40000000,
        0x02000000,0x40080000,0x40080000,0x00000000,
        0x40000100,0x42080100,0x42080100,0x02000100,
        0x42080000,0x40000100,0x00000000,0x42000000,
        0x02080100,0x02000000,0x42000000,0x00080100,
        0x00080000,0x42000100,0x00000100,0x02000000,
        0x40000000,0x02080000,0x42000100,0x40080100,
        0x02000100,0x40000000,0x42080000,0x02080100,
        0x40080100,0x00000100,0x02000000,0x42080000,
        0x42080100,0x00080100,0x42000000,0x42080100,
        0x02080000,0x00000000,0x40080000,0x42000000,
        0x00080100,0x02000100,0x40000100,0x00080000,
        0x00000000,0x40080000,0x02080100,0x40000100};
    int dword_5F4CB0[] = {0x00200000,0x04200002,0x04000802,0x00000000,
        0x00000800,0x04000802,0x00200802,0x04200800,
        0x04200802,0x00200000,0x00000000,0x04000002,
        0x00000002,0x04000000,0x04200002,0x00000802,
        0x04000800,0x00200802,0x00200002,0x04000800,
        0x04000002,0x04200000,0x04200800,0x00200002,
        0x04200000,0x00000800,0x00000802,0x04200802,
        0x00200800,0x00000002,0x04000000,0x00200800,
        0x04000000,0x00200800,0x00200000,0x04000802,
        0x04000802,0x04200002,0x04200002,0x00000002,
        0x00200002,0x04000000,0x04000800,0x00200000,
        0x04200800,0x00000802,0x00200802,0x04200800,
        0x00000802,0x04000002,0x04200802,0x04200000,
        0x00200800,0x00000000,0x00000002,0x04200802,
        0x00000000,0x00200802,0x04200000,0x00000800,
        0x04000002,0x04000800,0x00000800,0x00200002};
    
    //memset(&v5, -858993460, 0x54u);
    v7 = *(DWORD *)a1;
    v8 = *(DWORD *)(a1 + 4);
    v9 = (v8 ^ (v7 >> 4)) & 0xF0F0F0F;
    v8 ^= v9;
    v7 ^= 16 * v9;
    v9 = (unsigned __int16)(v8 ^ HIWORD(v7));
    v8 ^= v9;
    v7 ^= v9 << 16;
    v9 = (v7 ^ (v8 >> 2)) & 0x33333333;
    v7 ^= v9;
    v8 ^= 4 * v9;
    v2 = v7 ^ (v8 >> 8);
    v7 ^= v2 & 0xFF00FF;
    v8 ^= (v2 & 0xFF00FF) << 8;
    v8 = (v8 >> 31) & 1 | 2 * v8;
    v9 = (v8 ^ v7) & 0xAAAAAAAA;
    v7 ^= v9;
    v8 ^= v9;
    v7 = (v7 >> 31) & 1 | 2 * v7;
    for ( i = 0; i < 8; ++i )
    {
        v9 = (v8 >> 4) | (v8 << 28);
        v9 = *(DWORD *)a2 ^ ((v8 >> 4) | (v8 << 28));
        v11 = a2 + 4;
        v10 = dword_5F4CB0[v9 & 0x3F];
        v10 |= dword_5F4AB0[(v9 >> 8) & 0x3F];
        v10 |= dword_5F48B0[(v9 >> 16) & 0x3F];
        v10 |= dword_5F46B0[(v9 >> 24) & 0x3F];
        v9 = *(DWORD *)v11 ^ v8;
        v11 += 4;
        v10 |= dword_5F4DB0[v9 & 0x3F];
        v10 |= dword_5F4BB0[(v9 >> 8) & 0x3F];
        v10 |= dword_5F49B0[(v9 >> 16) & 0x3F];
        v10 |= dword_5F47B0[(v9 >> 24) & 0x3F];
        v7 ^= v10;
        v9 = (v7 >> 4) | (v7 << 28);
        v9 = *(DWORD *)v11 ^ ((v7 >> 4) | (v7 << 28));
        v11 += 4;
        v10 = dword_5F4CB0[v9 & 0x3F];
        v10 |= dword_5F4AB0[(v9 >> 8) & 0x3F];
        v10 |= dword_5F48B0[(v9 >> 16) & 0x3F];
        v10 |= dword_5F46B0[(v9 >> 24) & 0x3F];
        v9 = *(DWORD *)v11 ^ v7;
        a2 = v11 + 4;
        v10 |= dword_5F4DB0[v9 & 0x3F];
        v10 |= dword_5F4BB0[(v9 >> 8) & 0x3F];
        v10 |= dword_5F49B0[(v9 >> 16) & 0x3F];
        v10 |= dword_5F47B0[(v9 >> 24) & 0x3F];
        v8 ^= v10;
    }
    v8 = (v8 >> 1) | (v8 << 31);
    v9 = (v8 ^ v7) & 0xAAAAAAAA;
    v7 ^= v9;
    v8 ^= v9;
    v7 = (v7 >> 1) | (v7 << 31);
    v3 = v8 ^ (v7 >> 8);
    v8 ^= v3 & 0xFF00FF;
    v7 ^= (v3 & 0xFF00FF) << 8;
    v9 = (v8 ^ (v7 >> 2)) & 0x33333333;
    v8 ^= v9;
    v7 ^= 4 * v9;
    v9 = (unsigned __int16)(v7 ^ HIWORD(v8));
    v7 ^= v9;
    v8 ^= v9 << 16;
    v9 = (v7 ^ (v8 >> 4)) & 0xF0F0F0F;
    v7 ^= v9;
    v8 ^= 16 * v9;
    *(DWORD *)a1 = v8;
    result = v7;
    *(DWORD *)(a1 + 4) = v7;
    return result;
}
经过三次函数2的变换后,函数3即将18f278处的数据再以4个字节为单位,倒叙复制到别处。
若参数1的长度大于8,会循环再次调用后两个函数,并多加一步如下(后面会给出具体代码):
(*(DWORD*)str12)^=(*(DWORD*)(str11+8));
然后分析函数00401032 
里面还是有很多迷惑的函数,关键地方为:
00405533   .  50            push eax
00405534   .  8D8D ECFEFFFF lea ecx,dword ptr ss:[ebp-0x114]
0040553A   .  E8 79BCFFFF   call Key-enc.004011B8                    ;  关键
进去分析,得到的算法如下,str为传入的字符串,第二次关键函数是92 A8 01 86 FB BA 80 4B 
第五次关键函数是30 38 46 32 44 39 44 30 34 45 35 36 33 36 37 36 44 45 44 34 42 41 41 42 38 34 44 32 35 34 39 36
void Fun2(int str,int size)
{  
    char buff[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"};
    char buff2[50];
    int sum = size/3;
    int yu = size%3;
    int i;
    for (i = 0;i<sum;i++)
    {
        buff2[4*i] = buff[(UCHAR)((char *)str)[3*i]>>2];//第一个
        buff2[1+4*i] = buff[((((char *)str)[1+3*i] & 0xF0) >> 4) | 16 * (((char *)str)[3*i] & 3)];
        buff2[2+4*i] = buff[((((char *)str)[2+3*i] & 0xC0) >> 6) | 4 * (((char *)str)[1+3*i] & 0xF)];
        buff2[4*i+3] = buff[((char *)str)[2+3*i] & 0x3F];
    }
    if (yu == 1)
    {
        buff2[4*i] = buff[(UCHAR)(((char *)str)[3*i])>>2];
        buff2[4*i+1] = buff[16 * (((char *)str)[3*i] & 3)];
        buff2[4*i+2] = '=';
        buff2[4*i+3] = '=';
    } 
    else
        if (yu == 2)
        {
            buff2[4*i] = buff[(unsigned char)(((char *)str)[3*i])>>2];//第一个
            buff2[1+4*i] = buff[((((char *)str)[1+3*i] & 0xF0) >> 4) | 16 * (((char *)str)[3*i] & 3)];
            buff2[4*i+2] = buff[4 * (((char *)str)[1+3*i] & 0xF)];
            buff2[4*i+3] = '=';
        }
        for (int j = 0;j<4*(sum+1);j++)
        {
            BUFF2[j] = buff2[j];
        }
    return;
}
在第五次关键函数完成后,即可出现密文MDhGMkQ5RDA0RTU2MzY3NkRFRDRCQUFCODREMjU0OTY=
具体的算法应该就是这些,根据这些流程,现在已知密文:
NDE4OUM3MUVBNUZFOTFBM0NCRUI5OTcyMDUzN0VBNEIzMjIxRUIxNDhCOTU3Mzcw= 
经过第五个关键函数和第四个关键函数,得到数据为41 88 C7 0E A4 FE 81 A0   CB DB 98 72 05 34 EA 4B   30 21 DB 14 8B 85 70 70
char buff[] = "NDE4OUM3MUVBNUZFOTFBM0NCRUI5OTcyMDUzN0VBNEIzMjIxRUIxNDhCOTU3Mzcw=";
  char buff2[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  char buff3[49] = {0};
  int len = strlen(buff);
  int num = len/4;
  UCHAR j,data1,data2;
  for (int i=0;i<16;i++)
  {
    for (j = 0;j<64;j++)
    {
      if (buff2[j] == buff[4*i])
        break;
    }
    buff3[3*i] = 4*j;
    
    for (j = 0;j<64;j++)
    {
      if (buff2[j] == buff[4*i+1])
        break;
    }
    data1 = 16*j;
    data1&=0xf0;

    for (j = 0;j<64;j++)
    {
      if (buff2[j] == buff[4*i+2])
        break;
    }
    data2 = j/4;
    buff3[3*i+1] = data1|data2;

    for (j = 0;j<64;j++)
    {
      if (buff2[j] == buff[4*i+3])
        break;
    }
    if (j<30)
    {
      buff3[3*i+2] = j|0x40;
    } 
    else
    {
      buff3[3*i+2] = j;
    }
    
  }
  printf("%s\n",buff3);
}
//41 88 C7 0E A4 FE 81 A0   CB DB 98 72 05 34 EA 4B   30 21 DB 14 8B 85 70 70
对于第三个关键调用即 
unsigned int __cdecl sub_40D880(int a1, int a2)反向推的时候还是比较复杂,不知道有没有简单的方法。整个程序的关键流程基本都比较清楚了。
即:
代码1(00401208 ) 输入数据                自身关键数据1   
代码2(00401032) 代码1得到的数据    
代码3(00401208 ) 代码2得到的数据     自身关键数据2   
代码4(00401005) 一个简单的变换    
代码5(00401032) 代码4得到的数据    

有兴趣的可以继续跟着逆向下,哎,每天白天忙着上课,到晚上才能看看,不能连续性的做,纠结啊…… 
Key-enc.zip
Key-enc.txt


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

上传的附件:
收藏
免费 5
支持
分享
最新回复 (24)
雪    币: 29
活跃值: (499)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
2
楼主威武!小弟才开始接触破解,刚把汇编学完,还不会用IDA,到时候望楼主不吝赐教啊!
2013-9-25 23:27
0
雪    币: 33
活跃值: (779)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
搜常量  应该是des
2013-9-25 23:48
0
雪    币: 103
活跃值: (126)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
4
嘿嘿 加油 一起努力
2013-9-25 23:57
0
雪    币: 103
活跃值: (126)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
5
哦?我会看看的
2013-9-25 23:59
0
雪    币: 107
活跃值: (404)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
好长啊.谢谢撸主分享
2013-9-26 08:45
0
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
不错的说。
2013-9-26 09:11
0
雪    币: 185
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
单纯的看S表的话。 很像DES算法。
2013-9-26 09:17
0
雪    币: 458
活跃值: (306)
能力值: ( LV12,RANK:400 )
在线值:
发帖
回帖
粉丝
9
看楼主有点像成信的?这个题目我好像去年见过。。
2013-9-26 09:27
0
雪    币: 82
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
楼主非常威武
2013-9-26 09:31
0
雪    币: 6
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
抽时间做一做看
2013-9-26 09:31
0
雪    币: 45
活跃值: (55)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
12
这个好,我也玩下
2013-9-26 09:36
0
雪    币: 341
活跃值: (138)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
13
贴DES算法。。。。。
2013-9-26 10:16
0
雪    币: 1906
活跃值: (712)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
学习了,支持分享
2013-9-26 10:24
0
雪    币: 219
活跃值: (778)
能力值: (RANK:290 )
在线值:
发帖
回帖
粉丝
15
mark xian
2013-9-26 11:06
0
雪    币: 190
活跃值: (40)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
16
酱油哥,咱两都还没有精华,怎么办/?
2013-9-26 12:53
0
雪    币: 262
活跃值: (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
mark 下
2013-9-26 17:26
0
雪    币: 30
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
如果是标准的DES,找到密钥就OK了。
2013-9-26 18:45
0
雪    币: 1933
活跃值: (113)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
谢谢楼主分享 ,我会向楼主学习的
2013-9-27 01:11
0
雪    币: 345
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
两轮3DES,结果二进制转换成ascii码字符串,再base64就是最终结果了
2013-9-27 14:07
0
雪    币: 345
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
key的话并不是固定的,但是算法是没啥问题
2013-9-27 14:55
0
雪    币: 103
活跃值: (126)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
22
最近密码学刚好在学DES 看来还得学习……
2013-9-27 18:39
0
雪    币: 645
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
不错的小程序 下来 看看
2013-9-27 19:36
0
雪    币: 61
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
mark下
2013-9-27 21:08
0
雪    币: 403
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
对于一个不懂密码的人来说实在是吃力,现在才有点看懂
2013-9-27 21:25
0
游客
登录 | 注册 方可回帖
返回
//