前言
这是某位前辈的软件,因为加密狗丢了,所以没法用,叫我帮他破解一下看看,我也不确定破解能成功与否,然后这里记录一下过程
刚刚试了一下大概的破解,都不行,这个程序会在运行的时候,先和加密狗通信,确定加密狗存在之后,才会继续运行程序,现在我们就试试,就当练练手
1.软件截图
当我们运行这个软件的时候,如果没有加密狗,会崩出这个东西
然后用IDA
打开看看
这里很奇怪
因为一般IDA
打开之后,会提示你要不要看那个关系图,除非你关了才没有,但是这个程序不会跳出那个东西
那我们之后无图分析了
函数开始的时候就是做一些基本操作
然后就是准备调用这个0040721c
,我们这里留个路标,这里注释一下是我们第一个遇到的函数,比如function_1
之类的
我们进来这个函数看看
这里压入了一个参数EBX
和0
,然后就调用了这个函数GetModuleHandleA
这个函数
然后EBX
的值现在是
这个值是分配给程序的内存未初始化的垃圾值
所以这个函数是这样的GetModuleHandleA(NULL)
,返回调用进程本身的句柄
这里是要返回这个程序本身的句柄
然后这个函数的返回值是一个字符串
然后下面继续执行
这里将EAX
赋值给了DS: [75A0B8]
然后将EAX
置为0
之后,又赋值给了DS: [75A0BC]
和DS: [75A0C0]
然后便是调用函数call 00407210
这个东西
其实这个函数就在上面
这里将一个函数赋值给了EAX
之后
开始调用00406A04
这个函数
然后就是进入下面这些函数
最后函数返回之后
这里EDX
和EAX
是相同的值
然后就准备调用函数004047A8
,我们单步调试进去看看
这里其他都不重要,重要的是这个调用的函数004046A0
这里做了一些基本的函数操作
然后就返回了
然后从这个小函数出来后调用了这个00404748
我们单步进入看看
1-5
行都是一些基本的函数操作
然后第六行的地方
将这个值00758F08
赋值给了EAX
然后test
看看EAX
是否为0
,如果为0
的话,JE
跳转,在OD
中懒得改结果跳去看看的话,可以用IDA
搜索这个地址看看
这个函数是退出函数,把栈中的这些值都弹出,然后就返回
然后把EBX
置0
之后,和ESI
进行比较
到这里的时候,我们看一下寄存器值
EBX
已经被置为了0
,不论怎么运行代码,这个值到这里的时候肯定都0
,然后ESI
的值我们可以看看是哪里改变的
最近一次修改ESI
的值是这里,将EAX
的值赋值给了它
这里比较之后,这里是用JLE
这个指令,这个指令跳转的条件是ZF=1 or SF<>OF
什么SF
什么OF
什么的我们暂时不管,就看ZF
的值,如果CMP ESI, EBX
中,ESI
和EBX
的值相等,ZF
=1
,那这个JLE
就会跳转,这时候就不用管SF
和OF
了
然后我们看看会跳去哪里
然后这个函数就是来到这里,做了一些操作之后,又会跳去4047A2
这个地方,4047A2
之后就会返回了
看来这个函数是不能跳转的
函数这里通过一个赋值给EAX
的方式,调用函数
MOV EAX, DWORD PTR DS: [EDI + EBX * 8]
这个指令,EBX
刚刚才被置为了0
这里就是把EDI
的地址执行的值给了EAX
这个地方
现在的EAX
=00407290
, 这个函数我们可以用IDA
找找看看
就是这里,然后我们执行,此时对应内存地址的内存如下
执行之后
这里稍微说明一下BYTE
、WORD
还是DWORD
,BYTE
字面意思就是只会修改一位的数据,也是就FF
这么多,WORD
的话就是FF FF
,DWORD
就是FF FF FF FF
这么多的数据
这个函数把76366c
的数据都置为了F
,因为-1
表示为FF ...
嘛
然后就return
了函数
然后就是这些函数
这里还是要ESI
和EBX
比较大小,这和上面那个是一样的
这时候的寄存器的值
ESI
=12Eh
也就是302d
,然后EBX
=1
不过这里的跳转指令是JG
了,这个函数的跳转是ZF=0 or SF=OF
我们看看要跳转的地址是什么
这个函数也就是我们刚刚上面执行过的地址
也就这个指令会一直不断的执行这个跳转,循环302
遍,,然后直到ESI
=EBX
,我们再回去看看,下一个要执行的EAX
是多少
上一个EAX
的值是407290
,我们看看此时的EDI
然后是在内存中的值
左上角的四位就是我们刚刚执行那个函数的地址,在地址407290
上的操作是
就是把内存地址都置为F
的那个操作
然后我们看看下一个地址
然后下一个地址就是407084
,也就是内存中的下一行数据的前四个
这个函数在IDA
中显示如下
第一行的指令是将7635BC
地址上DWORD
大小,也就是4
个BYTE
的空间都置为F
然后就是JNB
,这个跳转的条件是CF=0
,也就是进位标志位,要求就是上面那个操作没有产生进位
我们去内存中看看7635BC
地址上的数据
不出所料,都是0
,那sub
之后肯定会产生一个借位,所以一定的是CF
=1
的确,我们执行完之后,CF
=1
然后这个函数就会跳转,我们看看会跳到哪里
函数跳转之后就是一个返回结束,我们看看如果不返回会发生什么
所以如果没有产生借位,就会返回退出,这是一种测试内存地址是否为0
的方式
然后我突然就把这个软件破解了。。。。不写了。。。就是一个判断跳转改一下的问题哈哈哈