反破解小技巧总结

2017-02-24  本文已影响335人  Fa1se003

网上看了一大堆,七零八碎的凑到一起的

1:ZwSetInformationThread,
该函数可以移除调试线程,遗憾的是StrongOD.dll 在r0下已经HOOK 了此函数,所以该函数无论如何调用,总是返回成功。但实际并没有移除。
好了,我们可以根据这个函数来判定 StrongOD.dll 是否存在,如何判定,这里不说了,说了以后,该插件估计就要升级啦!

2:GetTickCount 和 GetLocalTime
获取运行时间
比如,我一个定时器,1秒一次,不断的获取时间,

static int Old_Time = GetTickCount();
if(GetTickCount() - Old_Time <=3000)
Old_Time = GetTickCount();
else
{
MessageBox(Null,"程序被调试了","",0);
Old_Time = GetTickCount();
}

定时器1秒一次,高于3秒钟,说明我们当前线程被暂停运行过。只有调试的时候才会暂停线程,程序肯定被调试了。
因为是程序正常调用,所以呵呵,目前任何OD都无法绕过该检测.....

有人说,我在你GetTickCount 处下断点,不就能找到你检测代码了吗?
别急,咱们自己构建这个函数,不用系统的。

DWORD __stdcall MyGetTickCount()
{
DWORD nValue = 0;
__asm
{
MOV EDX,0x7FFE0000
MOV EAX,DWORD PTR DS:[EDX]
MUL DWORD PTR DS:[EDX+4]
SHRD EAX,EDX,0x18
MOV nValue,EAX
}
return nValue;
}
这下破解者会很苦逼的。

3:既然GetTickCount 检测如此牛逼,我们可以在检测代码处进行下进行多重校验。
大多数验证代码都是这样的
call xxxxxx
cmp eax,1
je 验证通过
//执行验证失败代码

很多人通过修改汇编代码,je 改写成 jmp来实现他们邪恶的目的。
7C809377 /0F85 7A080300 JNZ kernel32.7C839BF7
7C80937D |3977 34 CMP DWORD PTR DS:[EDI+34],ESI
7C809380 |0F85 3D040000 JNZ kernel32.7C8097C3

7C809377 /0F85 7A080300 JNZ kernel32.7C839BF7
7C80937D |3977 34 CMP DWORD PTR DS:[EDI+34],ESI
7C809380 |E9 3E040000 JMP kernel32.7C8097C3
7C809385 |90 NOP

我们可以看到7C809380处jnz 修改成 jmp 后,它对应的HEX 数据也从 0F85 改写成E9,如何检测,让他只要修改任意一条指令就能被我们发现。
其实方法很简单,只要在地址7C809377开始,读取指定字节,然后把数据累加下。它是一个固定的值。
方法:开几个线程互相对对方监控,
线程1监控线程2,线程2监控线程1,线程3监控线程1,只要一处代码被修改,都能检测到。也可以对一些敏感的API进行监控,
比如recv,send 因为WPE之类的抓包工具都会对函数进行HOOK.

4:检测到这些可恶的家伙在弄我们的程序,要ExitProcess退出吗?
当然不,他会在 TerminateProcess 和 ExitProcess 下断点等着你呢。我们可以直接破坏自己的程序,让程序异常退出。
比如,在程序里弄个死循环,无限申请内存,导致内存泄露,
比如,把数组里的数据给清空,导致访问异常。总之,搞死自己就可以了,别用API退出。

5:关键数据放服务器上,进行时间加密,确保每次封包都不一样,比如,很多外挂,把基址放服务器上,你爆破后,有界面没功能。

6:采用lua类似的模型。开辟一个独立的线程,所有的功能都集中在一个函数中完成

void Run(int nIndex)
{
//我们可以对nIndex 的不同类型,完成不同的敏感操作,
比如
为1:我们显示窗口
为2:弹出窗口
为3:设置字符串
}
由于Run和我们的验证代码不在一个线程里,所以,他很难通过栈回溯来找到关键call,增加破解难度。

7:字符串加密,在计算机语言里,有个叫异或运算的简单加密方式
字符a 和一个密匙进行异或后 变成另一个数
在异或运算一次,就又变回 a

int a = a ^ Password; //让a 和一个密匙加密
a = a ^ Password; //所得结果和同一个密匙运算一次,还原
因此,把字符串以int 数组的方式保存,然后用密匙还原。确保OD搜索插件搜不到。

1、检测调试寄存器

(1)检测 softice 等系统级调试器

检测softice的方法有很多.检测主要在驱动里中实现。

(2)监测用户级调试器用户级调试器具有一下几个特征:

用户级调试器是采用microsoft提供的dbghelp.dll库来实现对软件跟踪调试的。

被调试的软件其父进程为调试器。

所以可以采用如下的方法来检测:

a.调用api函数isdebuggerpresent()(或是直接采用isdebuggerpresent的反汇编代码,以防破解者拦截对该函数的调用)来检测是否有用户级调试器存在。

b.监测调试寄存器的方法。

c.采用tlb的方法,检查父进程的方法. 在winnt下,可以采用进程注入的技术来检测软件的父进程是否正确的方法。

d.设置seh进行反跟踪。

由于破解者者可以拦截软件对调试器的检测操作,所以将保护判断加在驱动程序中。因为驱动程序在访问系统资源时受到的限制比普通应用程序少得多,这也给了破解者增加了破解的难度。

2、crc检校

增加对软件自身的完整性检查。这包括对磁盘文件和内存映像的检查,以防止破解者未经允许修改程序以达到破解的目的。dll和exe之间可以互相检查完整性。

为了防止破解者采用替代word,以及edocguard的dll,通过计算dll的crc值来验证。

3、运行时库的重新编写

破解者往往是在hmemcpy,strcpy等运行时库函数上下断点,通过分析其中的字符串来窥视程序的内部运行。对于edocguard,虽然不是密码的处理,但是内存解密的部分就是使用的memcpy,所以需要重新编写这些运行时库,这个可以从vc或其他编译器的运行时库中的代码改写获得。

需要修改的是vc6_encry_lib,clinetfile里面,hook dll里面的readfile,驱动里的解密。

4、花指令的添加

用花指令来对付静态汇编是很有效的,这会使解密者无法一眼看到全部指令,杜绝了先把程序打印下来再慢慢分析的做法。

一条指令的长度是不等长的,假使有一条指令为 3 字节长,从它的第二个字节开始反汇编,会看到一条面目全非的指令,‘花指令’就是在指令流中插入很多‘垃圾’,使静态反汇编无法进行。

5、干扰代码的添加

在关键部位添加jmp nop cmp 等跳转指令,比较指令以及一些没返回的循环等。插入这些大量无用的运算以误导解密者,防止静态反汇编,增加破解者动态汇编时难度。

到处贴条件转移

没有循环,只是跳转,作为有条件的路障,这样,没有简单的反向操作可以执行。

6、api函数的不规则调用

在软件中对于api的调用不采用直接调用api的方法,因为这样破解者很容易了解到软件所调用的api,进而了解到软件的工作流程。可以采用由dll的输出表来定位api的函数地址的方法。

对于调试器来说,在对api设置断点时,是在api函数地址上添加一个int 3指令。所以在调用api时,把api的前几个代码指令复制到调用处,执行前几个代码指令,然后跳转到api函数中。

这样调试器对于api断点的监视是无效的。

7、接口与字符串

dll,com不使用有意义的函数接口.不采用一目了然的名字来命名函数和文件,如openfile( )、setpermisson等。

所有可能被破解者利用的字符串都不以明文形式直接存放在可执行文件中,采用加密的形式,在需要时进行解密。

尽可能少地给用户提示信息以防解密者直接了解软件的流程。比如,当检测到破解企图之后,不要立即给用户提示信息,而是在系统的某个地方做一个记号,随机地过一段时间后使软件停止工作,或者装作正常工作但实际上却在所处理的数据中加入了一些垃圾。

8、输入表输出表拦截的检测

定时检测软件各个模块的输入输出表是否一致,输入表、输出表中的函数地址是否处于对应模块的内存区域中,防止破解者采用hook api 的方法对软件进程破解操作。

9、加壳

软件最终发行之前将可执行程序进行加壳/压缩,使得解密者无法直接修改程序。如果采用现成的加壳工具,最好不选择流行的工具,因为这些工具已被广泛深入地加以研究,有了通用的脱壳/解压办法。另外,采用两种以上的不同的工具来对程序进行加壳/压缩,并尽可能地利用这些工具提供的反跟踪特性。

10、有条件允许使用加密狗,加密狗尽量选最新的,因为许多解密者对于新狗是没有研究的,即使他本人精通加密狗,也需要花费一段时间才能弄懂,这就为你的软件在第一时间销售争取到足够的时间。
  
  11、发布功能不全的软件提供免费试用,正版则要花钱购买。这样即使解密者破解了软件但因为功能不全,他一样相当于什么也没得到,而只有汇款给你的人才能得到功能齐全的版本。

12、推出无需注册的免费软件,这个不是一般人能承受的起的,但是已经有许多人在做了,试想如果你的软件根本不用注册就能使用,那解密的人就会没有软件可破而下岗。同时你的软件也会在使用者中留下良好的口碑。大家都用你的软件,你就会逐渐成为市场的主流,而你的同行恐怕就会慢慢退出市场了。

13、在软件中加入一些程序,使软件在运行一段时间后自动丢失信息或自动销毁或突然死机。如财务管理软件,这样一来使用者会担心自己因为使用破解版本造成巨大损失,而不得不主动购买你的正版软件。

14、
  15、上面没有写是想给你们留下广阔的空间,我相信每一位聪明人看了这13条之后都能独立想出一个行之有效的办法来保护你的软件。那这一条就教由你自己来完成了。
最后一条就是联合起来,搞破解的人可以联合,所以他们破一个软件会很容易,因为那不是某个人的智慧而是多个人的智慧,反过来,搞软件研发的人也应该联合起来,这样你们的保护才能不断的完善。采用高难度算法,如果想在算法上更胜一筹就得换成不可逆算法,让破解者找不到头绪。如同走迷宫,我介绍一种方法,不是CRC,因为我是应试教育的受害者,本人数学只会解方程。如果把方程应用到算法中会很有效。比如
设注册码为:X,Y两部分,
x,y的运算过程是:x,y是方程组:
      2    3
     X Y - X  -331 Y  =19     编程后为:XXY- XXX-331*Y=19

2  2
     X Y -X -1312 Y =38
的两根,把你的注册码两部分经过代入方程组中检验,这样破解者推出方程,根本解不出来。
他累死也不会想到 X=26 Y=51,其它值均错误。既你的注册码前一部分是26,后一部分是51,这样看起来好象并没有多大作用,但是x,y并不完全是固定的数字,可以是你的注册码每一位字母或数字的ascii码相加之和,经过四则运算,再减去一个数的结果。最后x,y的值可以不超过百位数,x,y也就可以按你的需要赋值了。像这样的方程我这里要多少有多少,保证X,Y解全都不一样,当然只是举一个很简单的例子

侵删。

上一篇下一篇

猜你喜欢

热点阅读