一含自杀代码的软件注册算法分析
准备阶段:分别对硬盘序列号和厂商编码进行计算,得到两组数据,到这里成型:
[*]0048934C MOV EDX, DWORD PTR DS: ;数字 25517715
[*]00489352 PUSH EDX ; /Arg1 => 0020EFDC
[*]00489353 CALL NEAR DWORD PTR DS:[<&msvbvm60.rtcR8ValFromBs>; \转化为整数
[*]00489359 MOV EBX, DWORD PTR DS:[<&msvbvm60.__vbaFpI4>] ;msvbvm60.__vbaFpI4
[*]0048935F CALL NEAR EBX ;<&msvbvm60.__vbaFpI4>
[*]00489361 XOR EAX, 246E69 ;25517715 xor 246E69=27341050
[*]00489366 PUSH EAX ; /Arg1
[*]00489367 CALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaStrI4>] ; \转化为数字--结果1
[*]0048936D MOV EDX, EAX
[*]0048936F MOV ECX, u中文内?0050D05C
[*]00489374 CALL NEAR ESI
[*]00489376 MOV EAX, DWORD PTR DS: ;数字 35567050
[*]0048937B PUSH EAX ; /35567050
[*]0048937C CALL NEAR DWORD PTR DS:[<&msvbvm60.rtcR8ValFromBs>; \转化为整数
[*]00489382 CALL NEAR EBX
[*]00489384 XOR EAX, 856AC5 ;35567050 xor 856AC5=43769615
[*]00489389 PUSH EAX ; /Arg1
[*]0048938A CALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaStrI4>] ; \转化为数字--结果2
复制代码
虽说后面还要对结果1、2进行计算,但
结果1=27341050
结果2=43769615
是重要的步骤过程。
接下来是重启之后的重要校验:
[*]0048939C MOV EDX, DWORD PTR DS: ;43769615
[*]004893A2 PUSH 1 ; /Arg4 = 00000001
[*]004893A4 PUSH ECX ; |Arg3
[*]004893A5 PUSH EDX ; |Arg2 => 00207224
[*]004893A6 PUSH EDI ; |Arg1
[*]004893A7 CALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaInStr>] ; \43769615 在注册码解密数据中?
[*]004893AD MOV ECX, DWORD PTR DS: ;27341050
[*]004893B3 XOR EBX, EBX
[*]004893B5 TEST EAX, EAX
[*]004893B7 MOV EAX, DWORD PTR SS:
[*]004893BA PUSH 1 ; /Arg4 = 00000001
[*]004893BC PUSH EAX ; |Arg3
[*]004893BD PUSH ECX ; |Arg2 => 001984EC
[*]004893BE PUSH EDI ; |Arg1
[*]004893BF SETLE BL ; |
[*]004893C2 CALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaInStr>] ; \27341050 在注册码解密数据中?
复制代码
如果这里通不过的话,就要求进行软件注册了。
上面的校验过程省略了注册码的变换描述。
注册码变换:
[*]004726EFMOV DWORD PTR SS:, 5 ;循环==>
[*]……
[*]00472727CALL NEAR DWORD PTR DS:[<&msvbvm60.rtcMidCharVar>>; \读取注册码一位
[*]……
[*]00472752MOV DWORD PTR SS:, u中文内?00410C14 ;“-”
[*]……
[*]00472774CALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaVarTstEq>>; \是否是“-”
[*]……
[*]0047277FJE u中文内?00472A81 ;不是则跳
[*]……
[*]00472858CALL NEAR DWORD PTR DS:[<&msvbvm60.rtcMidCharVar>>; \是则截取“-”号前面一截
[*]……
[*]004729ACCALL u中文内?00472EC0 ;换序
[*]……
[*]004729CCCALL u中文内?00472150 ;换算
[*]……004729E8PUSH EDX ; /Arg3
[*]004729E9LEA EAX, DWORD PTR SS: ; |
[*]004729EFPUSH EAX ; |Arg2
[*]004729F0LEA ECX, DWORD PTR SS: ; |
[*]004729F6PUSH ECX ; |Arg1
[*]004729F7CALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaVarCat>]; \__vbaVarCat
[*]004729FDPUSH EAX ; /Arg3
[*]004729FELEA EDX, DWORD PTR SS: ; |
[*]00472A04PUSH EDX ; |Arg2
[*]00472A05LEA EAX, DWORD PTR SS: ; |
[*]00472A0BPUSH EAX ; |Arg1
[*]00472A0CCALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaVarCat>]; \__vbaVarCat--结果拼接
[*]……
[*]00472AADJNZ u中文内?004726EF ;循环<==
复制代码
注册分为n段,每段之间用“-”号连接,这段代码的作用就是按“-”将注册码进行切割,其中前n-1段注册码在这段代码中进行解密。解密的结果仍按原来的顺序用“-”号进行连接。
最后一段用下面的代码解密并连接:
[*]00472CE9CALL u中文内?00472EC0 ;换序
[*]……
[*]00472D09CALL u中文内?00472150 ;换算
[*]00472D0ELEA EDX, DWORD PTR SS:
[*]00472D11PUSH EDX ; /Arg3
[*]00472D12LEA EAX, DWORD PTR SS: ; |
[*]00472D18PUSH EAX ; |Arg2
[*]00472D19LEA ECX, DWORD PTR SS: ; |
[*]00472D1FPUSH ECX ; |Arg1
[*]00472D20CALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaVarCat>]; \__vbaVarCat
复制代码
其实处理方法完全相同。
前面的检验就是使用了这里解密的数据。
从前面的检验不难看到,注册码至少需要两段。
如果恰好两段,且也满足条件,是能够注册的,所有的使用和现实均正常。
如果你认为注册码恰好两段,那你就错了,在某个时刻(某个动作下)你会发现你的注册信息以及主程序悄然失踪。那就是说,程序还有暗桩。
请看:
[*]0048D1D2 PUSH u中文内?00411978 UNICODE "*.EXE"
[*]0048D1F2 MOV EDX, u中文内?00411988 UNICODE "in.bat"
[*]0048D216 PUSH u中文内?0041199C UNICODE ":START"
[*]0048D22A PUSH u中文内?004119B8 UNICODE "del "
[*]0048D252 PUSH u中文内?004119C8 UNICODE "if exist "
[*]0048D262 PUSH u中文内?004117B8 UNICODE " GOTO START"
[*]0048D28D PUSH u中文内?004119B8 UNICODE "del "
[*]0048D292 PUSH u中文内?00411988 UNICODE "in.bat"
复制代码
这些地址指示的位置是生成一个批处理程序"in.bat",然后反复寻找当前"程序名*.EXE",一经发现,立马"del ",当已经没有时,"in.bat"就自杀。
有了这段地址代码,定位相应代码就不成问题了。那触发这个批处理程序的原因是什么呢?接着看:
1、机器码和解密数据之间是什么关系呢:
回忆我的过程结果:
结果1=27341050
结果2=43769615
[*]0046BEA1MOV EAX, DWORD PTR DS: ;27341050
[*]……
[*]0046BEAACALL NEAR DWORD PTR DS:[<&msvbvm60.rtcR8ValFromBs>; \转化为整数
[*]……
[*]0046BEB8XOR EAX, 23D0B5 ;27341050 xor 23D0B5=25354319
[*]0046BEBDPUSH EAX ; /Arg1
[*]0046BEBECALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaStrI4>] ; \转化为数字
[*]……
[*]0046BECDMOV ECX, DWORD PTR DS: ;43769615
[*]0046BED3PUSH ECX ; /Arg1 => 00000000
[*]0046BED4CALL NEAR DWORD PTR DS:[<&msvbvm60.rtcR8ValFromBs>; \转化为整数
[*]0046BEDACALL NEAR EBX
[*]0046BEDCXOR EAX, 274996 ;43769615 xor 274996=45913753
[*]0046BEE1PUSH EAX ; /Arg1
[*]0046BEE2CALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaStrI4>] ; \转化为数字
[*]……
[*]0046BF05MOV ECX, DWORD PTR DS: ;25354319
[*]0046BF0BMOV EBX, DWORD PTR DS:
[*]0046BF0DPUSH ECX ; /Arg2 => 00000000
[*]0046BF0EPUSH u中文内?00410244 ; |Arg1 = 00410244
[*]0046BF13MOV DWORD PTR SS:, EAX ; |
[*]0046BF19CALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaStrCat>]; \拼接
[*]……
[*]0046BF26MOV EDX, DWORD PTR DS: ;45913753
[*]0046BF2CPUSH EAX ; /Arg2
[*]0046BF2DPUSH EDX ; |Arg1 => 00000000
[*]0046BF2ECALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaStrCat>]; \拼接成机器码
复制代码
而机器码恰好就是:25354319_45913753.
原来由机器码得到参与比较的数据要经过这样的计算。
2、注册码解密过程:
1)、换序
为便于观察,假设一段注册码为:12345678。换序后的结果为:81726354。
2)、换算
[*]0047234FMOV DWORD PTR SS:, 8 ;循环==>
[*]……
[*]0047238ACALL NEAR DWORD PTR DS:[<&msvbvm60.rtcMidCharVar>>; \读取一位
[*]……
[*]004723C4CALL NEAR DWORD PTR DS:[<&msvbvm60.rtcAnsiValueBs>; \取ASC码
[*]004723CAMOV SI, AX ;转移结果
[*]004723CDPUSH u中文内?00410C0C ; /C
[*]004723D2CALL NEAR DWORD PTR DS:[<&msvbvm60.rtcAnsiValueBs>; \取C的ASC码
[*]004723D8SUB SI, AX ;两者相减
[*]……
[*]00472426CALL NEAR DWORD PTR DS:[<&msvbvm60.rtcR8ValFromBs>; \取结果
[*]0047242CFADD QWORD PTR DS: ;+0.5
[*]00472432CMP DWORD PTR DS:, 0
[*]00472439JNZ SHORT u中文内?00472443
[*]0047243BFDIV QWORD PTR DS: ;/2.5
[*]……
[*]0047245ECALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaFPInt>] ;取整
[*]……
[*]004724A8CALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaVarCat>]; \转化为数字进行拼接
[*]……
[*]004724E8JNZ u中文内?0047234F ;循环<==
复制代码
经过这段代码的运算,注册码的每一段就算解密好了。
3、暗桩校验:
[*]004BA207CALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaInStrVar>>; \NMZH-是否在注册码中
[*]……
[*]004BA243TEST ECX, ECX
[*]004BA245JE SHORT u中文内?004BA26D ; 在就跳
[*]……
[*]004BA252CALL u中文内?0048D380 ;跳至批处理
[*]004BA257LEA ECX, DWORD PTR SS:
[*]004BA25ACALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaFreeVar>] ;msvbvm60.__vbaFreeVar
[*]004BA260MOV DWORD PTR SS:, 15 ; |
[*]004BA267CALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaEnd>] ; \__vbaEnd
[*]004BA26DMOV DWORD PTR SS:, 17
[*]……
[*]004BA293CALL u中文内?004725F0 ;注册码变换
[*]……
[*]004BA2A2CALL NEAR DWORD PTR DS:[<&msvbvm60.rtcRightCharVa>; \读取解码结果的后4位
[*]……
[*]004BA2CCCALL NEAR DWORD PTR DS:[<&msvbvm60.rtcRightCharVa>; \读取机器码计算过程中间值的后4位
[*]……
[*]004BA2DDCALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaVarTstNe>>; \比较
[*]……
[*]004BA30BTEST EDX, EDX
[*]004BA30DJE SHORT u中文内?004BA335
[*]……
[*]004BA31ACALL u中文内?0048D380 ;跳至批处理
[*]004BA31FLEA ECX, DWORD PTR SS:
[*]004BA322CALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaFreeVar>] ;msvbvm60.__vbaFreeVar
[*]004BA328MOV DWORD PTR SS:, 19 ; |
[*]004BA32FCALL NEAR DWORD PTR DS:[<&msvbvm60.__vbaEnd>] ; \__vbaEnd
[*]004BA335MOV DWORD PTR SS:, 1D
总结:
1、注册验证模式为:F(注册码)=机器码。
2、难点:分散式检验;
3、虽有破坏性代码,但只自杀,不伤及无辜。
[快捷回复]-学破解防逆向,知进攻懂防守!
[快捷回复]-软件反汇编逆向分析,软件安全必不可少! 在此留名,以后多多交流哦~ [吾爱汇编论坛52HB.COM]-感谢楼主热心分享!标记一下,先看看好不好,谢谢楼主咯! 感谢版主的分享 多谢大佬分享 [吾爱汇编论坛52HB.COM]-软件反汇编逆向分析,软件安全必不可少!
页:
[1]
2