逆向破解某公司信息管理软件
1.破解软件本文要破解的是一款类似公司信息管理的软件,本文简要分析一下软件的实现代码和破解的关键及如何使用脚本找到程序的oep。
软件的运行情况如下:
2.使用工具
1.pe explorer
2.Darkde
3.OD
4.ida
3.破解过程
1.查壳,aspack壳,OD载入,搜索命令push 0和retn,在006A13B0 jnz short Active_M.006A13BA处下断,f9,单步到oep,脱壳。
接着我写了一个脱壳脚本,但该脱壳脚本不能适用于所有的aspack壳VAR cc
FIND eip ,#6800000000c3#
MOV cc,$RESULT
BPHWS cc,"x"
RUN
MSG$RESULT
BPHWC cc
STO
STO
MSG "欢迎来到OEP"
AN eip
RET
运行结果:
上面我搜索了push 0 retn,接着突发奇想写了一个在ida中搜索push 0 retn的ida脚本,不过该脚本不能应用于该软件,因为加壳程序ida不能进行反汇编,大家参考思路就好。
import os
import sys
def getAns(ea_from,ea_to):
pre_cmd=''
pre_addr=0
cmd1=''
op_num=0
for start_a in Heads(ea_from,ea_to): #遍历指令地址
if isCode(GetFlags(start_a)): #判断是否为指令
cmd1=GetMnem(start_a) #获取指令名称
op_num=Dword(pre_addr+1) #push 后面的操作数
if pre_cmd=='push' and cmd1=="retn" and op_num==0x00000000:
Message("-->%08x\n"%(op_num))
Message("-->%08x%08s \n"%(start_a,cmd1))
Message("-->%08x%08s \n"%(pre_addr,pre_cmd))
MakeComm(start_a,"go oep") #添加注释
pre_cmd=cmd1 #上一个指令
pre_addr=start_a
Message("ok")
ea=ScreenEA()
for seg in Segments(): #遍历所有的段
if SegName(seg)=='.text':
getAns(seg,SegEnd(seg)) #把代码段的起始地址和结束地址传入
2.接着用pe explorer打开,点击PEexplorer上方的资源查看器按钮,接着点击RC data中的TFORMREGISTER,出现下拉列表,点开pnbutton,发现这两个按钮跟注册按钮无关,这两个按钮是软件下列列表中的按钮。
3.接着用Darkde打开,点开tfrmregister,发现里面的信息跟PEexplorer一样,那么只好用OD找到跟注册按钮相关的代码了。
4.OD载入,注册码输入123456,f9,f12,alt+k,点击最后一行函数dump_00457038,用ida打开,找到引用该函数的地方,随后在OD中找到并往上拉,在断首下段。
5.重加载,f9到0045f278push ebp,选中栈首按enter,找到调用它的地方,上拉,可以看到连接服务器的代码,在段首005Aaaf7c push ebp下断
6.接着在005AAFB3 je dumped_.005AB06A下断,单步,在005AB0F4 je dumped_.005AB17A下断,把005AB0F4 je dumped_.005AB17A nop掉,还是显示验证失败
7.运行到005AB1C0 call dumped_.005A9A8C发现该函数会对输入的字符串进行算法处理并生成字符串,而且生成的字符串,每次都不同,往下运行发现程序把生成的字符串拼接到验证服务器连接的后面发送到服务器,接着服务器验证发送过来的字符串,那么要破解这种服务器验证注册码的软件,只好使用暴力破解了,Nop掉005AB210 CALL dumped_.005AA210、005AB220JL SHORT dumped_.005AB262、005AB227 JG SHORT dumped_.005AB262、005AB230 JNZ SHORT dumped_.005AB262就可破解。
8.用ida打开,分析一下内部算法,找到连接服务器代码,看到嗯不同的键会对应不同的操作,注册和试用都会调用deal_code函数,接着进入deal_code函数。
9.在上面od中看到,注册码在eax中,那么a1位注册码,接着v31为注册码,下面是初始化操作。
10.deal_code函数,有一个比较重要的循环结构,每循环一次处理两个字符,另这两个字符为a,b,进入sub_5A9A48函数,发现该函数为十六进制转十进制数的函数,如果注册码字符不为十六进制数则返回0.
11.在上述循环结构中sub_5A9A48使用了两次,先后是计算a和b的十进制数,在OD中运行发现,计算a的十进制后左移4位,接着取低四位作为高位,加上b的十进制数(低四位),结果保存在dl中。在sub_402E40中发现,两个数(一个是oxff,一个是ds中的值)相乘之后把结果赋值给edx,随后赋值给ds中,ds记录了每次相乘后的结果,当注册码的长度小于32时,不够的部分全部充0,下面的代码没啥好讲的,就写到这了。
厉害,学习,学习。{:1_927:} 高端{:301_992:}只是看不懂 厉害了楼主支持一下 支持大佬! 楼主厉害,元旦快乐! 加密的 散了散了 太厉害了那 支持 学习下!!! 虽然看不懂 但是要赞一下