手磋汇编解密某视频软件

查看 106|回复 9
作者:feiyao32   
朋友发来的一个视频加密软件,跟了许久,留下点东西分享出来。
0、由于视频文件比较大,视频软件不会一次读取所有文件处理,而是分段处理,这样就可以跟踪到处理函数,而这个处理函数都是动态释放的,好在是函数没有加密。
1、一般处理函数的参数也就是,函数(密码相关信息,buffer,size)这样的,处理完以后下断通过od的脚本导出即可。
[C++] 纯文本查看 复制代码dma [esp-8], 8000, "z:\03.txt"
jmp justgo
cmps:   
cmp eip,100790ba //解密完的地方
je getapi
jmp end
getapi:
dma [esp-8], 8000, "z:\03.txt" //在堆栈里翻出buffer地址[esp-8],大小0x8000,追加存入文件 "z:\03.txt"
justgo:
RUN
jmp cmps
end:
这样虽然可以,但是一次只能处理32K的数据,od断点处理的效率很低,而且还有同步在播放,卡顿。于是乎想了一种办法来处理,何不直接用汇编打开文件来处理呢,不要让他播放了,思路是读文件,给到buffer,解密,再读文件。
通过脚本保存文件。最后还是觉得太麻烦,既然都写汇编了,何不直接把写文件也弄上呢?
3、做做准备工作
了解下api读写函数的参数调用,堆栈等,参数尽量通过堆栈存储和访问,尽量优雅的还原现场。相关的call可以直接修改为api函数或者解密函数,避免每次od跟踪数据地址不同的情况。用二进制数据保存写好的指令,中间预留一些9090,防止修改字节数不够。
准备了如下一些api:
打开文件:
[Asm] 纯文本查看 复制代码0019EF90   7ADDA8F4  /CALL 到 CreateFileA 来自 MSVBVM60.7ADDA8EE
0019EF94   0019F008  |FileName = "d:\nonamea.txt"
0019EF98   C0000000  |Access = GENERIC_READ|GENERIC_WRITE
0019EF9C   00000003  |ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE
0019EFA0   0019EFC8  |pSecurity = 0019EFC8
0019EFA4   00000004  |Mode = OPEN_ALWAYS
0019EFA8   00000080  |Attributes = NORMAL
0019EFAC   00000000  \hTemplateFile = NULL
读文件
[Asm] 纯文本查看 复制代码0019F09C   55600873         /CALL 到 ReadFile 来自 MSVBVM60.5560086D
0019F0A0   000002D0         |hFile = 000002D0 (window)
0019F0A4   005933D0         |Buffer = 005933D0
0019F0A8   000018F0         |BytesToRead = 18F0 (6384.)
0019F0AC   0019F0C8         |pBytesRead = 0019F0C8
0019F0B0   00000000         \pOverlapped = NULL
写文件
[Asm] 纯文本查看 复制代码0019EC58   7ADDB2AF  /CALL 到 WriteFile 来自 MSVBVM60.7ADDB2A9
0019EC5C   000002E4  |hFile = 000002E4
0019EC60   007846F4  |Buffer = 007846F4
0019EC64   00000004  |nBytesToWrite = 4
0019EC68   0019EC8C  |pBytesWritten = 0019EC8C
0019EC6C   00000000  \pOverlapped = NULL
移动文件读取位置
[Asm] 纯文本查看 复制代码76DBBF34    6A 00           push 0x0
76DBBF36    6A 00           push 0x0
76DBBF38    6A 03           push 0x3
76DBBF3A    68 48020000     push 0x248
76DBBF3F    E8 5C2FFAFF     call KERNEL32.SetFilePointer                         ; jmp 到 KERNELBA.SetFilePointer
关闭文件
[Asm] 纯文本查看 复制代码7ADDB381    50                     push eax
7ADDB382    FF15 5412DD7A          call dword ptr ds:[; KERNEL32.CloseHandle
4、直接上代码,后面都写好了注释了。
[Asm] 纯文本查看 复制代码10007D4D      90            nop
10007D4E      90            nop
10007D4F      90            nop
10007D50      83EC 20       sub esp,0x20                             ;  新eip开始,此处临时开辟32字节,输入文件名,打开文件,压入句柄,此处执行2次
10007D53      6A 00         push 0x0                                 ;  给打开文件输入参数
10007D55      68 80000000   push 0x80
10007D5A      6A 04         push 0x4
10007D5C      6A 00         push 0x0
10007D5E      6A 03         push 0x3
10007D60      68 000000C0   push 0xC0000000
10007D65      8BC4          mov eax,esp
10007D67      83C0 18       add eax,0x18
10007D6A      50            push eax
10007D6B      E8 604CC466   call KERNELBA.CreateFileA                ;  建立文件,eax返回句柄
10007D70      83C4 20       add esp,0x20                             ;  回收堆栈
10007D73      50            push eax                                 ;  此处保存需要处理的文件句柄,并从上次新建eip处,执行第二次,新建新文件,压入句柄
10007D74      6A 01         push 0x1                                 ;  占位,后来用作写入文件反馈的写入字节
10007D76      6A 02         push 0x2                                 ;  占位,后来用作读入文件反馈的读入字节
10007D78      6A 03         push 0x3                                 ;  修改为需要处理的buffer
10007D7A      6A 04         push 0x4                                 ;  读取文件的句柄
10007D7C      6A 05         push 0x5                                 ;  修改为读取反馈的指针,及push2 处的堆栈地址
10007D7E      6A 06         push 0x6                                 ;  修改为需要处理的文件开始指针
10007D80      6A 00         push 0x0                                 ;  文件指针移动的必要参数
10007D82      6A 00         push 0x0
10007D84      FF7424 08     push dword ptr ss:[esp+0x8]              ;  压入文件偏移
10007D88      FF7424 14     push dword ptr ss:[esp+0x14]             ;  压入文件句柄
10007D8C      90            nop
10007D8D      90            nop
10007D8E      90            nop
10007D8F      E8 0C714E65   call KERNEL32.SetFilePointer             ;  jmp 到 KERNELBA.SetFilePointer
10007D94      6A 00         push 0x0                                 ;  读取文件的参数
10007D96      FF7424 08     push dword ptr ss:[esp+0x8]
10007D9A      90            nop
10007D9B      68 00800000   push 0x8000                              ;  每次读取字节数
10007DA0      FF7424 18     push dword ptr ss:[esp+0x18]             ;  buffer
10007DA4      90            nop
10007DA5      FF7424 18     push dword ptr ss:[esp+0x18]             ;  读文件的句柄
10007DA9      90            nop
10007DAA      E8 61704E65   call KERNEL32.ReadFile                   ;  jmp 到 KERNELBA.ReadFile
10007DAF      90            nop
10007DB0      83F8 01       cmp eax,0x1
10007DB3      75 73         jnz Xcorem.10007E28                      ;  读取成功为1,否者跳走,下断点
10007DB5      3E:8B4424 10  mov eax,dword ptr ds:[esp+0x10]
10007DBA      3D 00800000   cmp eax,0x8000                           ;  比较读取的字节数,如果不是0x8000证明文件读取完毕
10007DBF      75 6F         jnz Xcorem.10007E30                      ;  跳转到最后半包数据的处理
10007DC1      B8 6057AA07   mov eax,0x7AA5760                        ;  初始化解密参数信息
10007DC6      C700 656C8174 mov dword ptr ds:[eax],0x74816C65
10007DCC      C740 04 EC0DB>mov dword ptr ds:[eax+0x4],0xE5B80DEC
10007DD3      C740 08 5EE5F>mov dword ptr ds:[eax+0x8],0xFAFAE55E
10007DDA      C740 0C 11F82>mov dword ptr ds:[eax+0xC],0xDC26F811    ;  初始化解密参数信息
10007DE1      68 00800000   push 0x8000                              ;  解密字节数
10007DE6      FF7424 10     push dword ptr ss:[esp+0x10]             ;  解密的buffer
10007DEA      FF7424 2C     push dword ptr ss:[esp+0x2C]             ;  解密的依赖信息,包含上面初始化的信息
10007DEE      E8 1D95FFFF   call corem.#11                           ;  调用解密函数,解密后,还是存在buffer里面
10007DF3      90            nop
10007DF4      6A 00         push 0x0                                 ;  写参数 pOverlapped = NULL
10007DF6      8BC4          mov eax,esp
10007DF8      83C0 18       add eax,0x18
10007DFB      50            push eax                                 ;  pBytesWritten
10007DFC      FF7424 18     push dword ptr ss:[esp+0x18]             ;  写字节 0x8000
10007E00      FF7424 18     push dword ptr ss:[esp+0x18]             ;  buffer
10007E04      FF7424 28     push dword ptr ss:[esp+0x28]             ;  hFile 写文件的句柄。
10007E08      E8 F3704E65   call KERNEL32.WriteFile                  ;  jmp 到 KERNELBA.WriteFile
10007E0D      33C0          xor eax,eax    ;清空eax
10007E0F      034424 10     add eax,dword ptr ss:[esp+0x10]   ;文件偏移
10007E13      030424        add eax,dword ptr ss:[esp]   ;文件偏移加上本次处理的字节。
10007E16      890424        mov dword ptr ss:[esp],eax   ;修改下次文件偏移的地址
10007E19    ^ E9 62FFFFFF   jmp corem.10007D80     ;回跳循环执行代码了。
10007E1E      90            nop
10007E1F      90            nop
10007E20      90            nop
10007E21      90            nop
10007E22      90            nop
10007E23      90            nop
10007E24      90            nop
10007E25      90            nop
10007E26      90            nop
10007E27      90            nop
10007E28      90            nop                                      ;  读取失败的断点
10007E29      90            nop
10007E2A      90            nop
10007E2B      90            nop
10007E2C      90            nop
10007E2D      90            nop
10007E2E      90            nop
10007E2F      90            nop
10007E30      B8 6057AA07   mov eax,0x7AA5760                        ;  处理最后半包数据,初始化解密参数
10007E35      C700 656C8174 mov dword ptr ds:[eax],0x74816C65
10007E3B      C740 04 EC0DB>mov dword ptr ds:[eax+0x4],0xE5B80DEC
10007E42      C740 08 5EE5F>mov dword ptr ds:[eax+0x8],0xFAFAE55E
10007E49      C740 0C 11F82>mov dword ptr ds:[eax+0xC],0xDC26F811
10007E50      FF7424 10     push dword ptr ss:[esp+0x10]
10007E54      90            nop
10007E55      FF7424 10     push dword ptr ss:[esp+0x10]
10007E59      FF7424 2C     push dword ptr ss:[esp+0x2C]
10007E5D      E8 AE94FFFF   call corem.#11                           ;  解密函数
10007E62      90            nop
10007E63      6A 00         push 0x0
10007E65      8BC4          mov eax,esp
10007E67      83C0 18       add eax,0x18
10007E6A      50            push eax
10007E6B      FF7424 18     push dword ptr ss:[esp+0x18]
10007E6F      FF7424 18     push dword ptr ss:[esp+0x18]
10007E73      FF7424 28     push dword ptr ss:[esp+0x28]
10007E77      E8 84704E65   call KERNEL32.WriteFile                  ;  jmp 到 KERNELBA.WriteFile
10007E7C      FF7424 18     push dword ptr ss:[esp+0x18]             ;  压入句柄,下一步关闭解密好的文件
10007E80      E8 8B694E65   call KERNEL32.CloseHandle                ;  jmp 到 KERNELBA.CloseHandle
10007E85      83C4 20       add esp,0x20                             ;  平衡堆栈,跳回去执行本来的解密函数
10007E88    ^ E9 8394FFFF   jmp corem.#11
10007E8D      90            nop
10007E8E      90            nop
5、最后的成品二进制代码
[Asm] 纯文本查看 复制代码90 90 90 83 EC 20 6A 00 68 80 00 00 00 6A 04 6A 00
6A 03 68 00 00 00 C0 8B C4 83 C0 18 50 E8 60 4C CC 6D 83 C4 20 50 6A 01 6A 02 6A 03 6A 04 6A 05
6A 06 6A 00 6A 00 FF 74 24 08 FF 74 24 14 90 90 90 E8 4C C8 CE 6D 6A 00 FF 74 24 08 90 68 00 80
00 00 FF 74 24 18 90 FF 74 24 18 90 E8 61 CB CE 6D 90 83 F8 01 75 73 3E 8B 44 24 10 3D 00 80 00
00 75 6F B8 60 57 AA 07 C7 00 65 6C 81 74 C7 40 04 EC 0D B8 E5 C7 40 08 5E E5 FA FA C7 40 0C 11
F8 26 DC 68 00 80 00 00 FF 74 24 10 FF 74 24 2C E8 5F 17 71 08 90 6A 00 8B C4 83 C0 18 50 FF 74
24 18 FF 74 24 18 FF 74 24 28 E8 03 D6 CE 6D 33 C0 03 44 24 10 03 04 24 89 04 24 E9 62 FF FF FF
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 B8 60 57 AA 07 C7 00 65 6C 81 74 C7 40 04
EC 0D B8 E5 C7 40 08 5E E5 FA FA C7 40 0C 11 F8 26 DC FF 74 24 10 90 FF 74 24 10 FF 74 24 2C E8
F0 16 71 08 90 6A 00 8B C4 83 C0 18 50 FF 74 24 18 FF 74 24 18 FF 74 24 28 E8 94 D5 CE 6D FF 74
24 18 E8 4B 65 CC 6D 83 C4 20 E9 83 94 FF FF 90 90 90 90 90 90 90

文件, 句柄

liwj   

膜拜大佬,太厉害了
wasm2023   

看着是某盾,这种分段加密真的恶心
nitian0963   

膜拜大佬,太厉害了
JakerPower   

太厉害了大佬,越看越觉得差距太大了
success67567381   

好家伙!大佬 666
guzhiduxiu   

厉害了,大佬666
soughing   

太厉害了大佬,越看越觉得差距太大了
zhou122333   

看着好深奥
chuying   

膜拜大佬,太厉害了
您需要登录后才可以回帖 登录 | 立即注册

返回顶部