Molet

破解入门:如何编写一个Linux 64位软件注册机

Molet 安全防护 2022-12-21 296浏览 0

本文仅供安全学习与教学用途,禁止任何非法利用

相信大家对注册机这词一定不陌生,由于一些软件涉及版权问题,要完全使用的话需要注册,或者有试用期限限制,或者只有注册之后才可以享受全功能。目前大部分有关于破解的资料都是基于X86架构的,而对于X64架构的破解资料却是比较少。

在本文中,我将向大家展示如何在Liunx机器上编写一个Linux 64位应用的注册机。

准备工作

我们将会使用到以下工具

1:Linux机器(64bitmintbox)
2:EDBdebugger
3:IDA反汇编工具
4:编译器
5:本文相关的文件(链接:http://pan.baidu.com/s/1hqti6LA密码:djnt)

运行file命令检测该文件类型

file r5

下面为返回数据

r5:ELF64-bitLSBexecutable,x86-64,version1(SYSV),dynamicallylinked(usessharedlibs),forGNU/Linux2.6.24,
BuildID[sha1]=86bf854ce620288567d153883d4609163485d34d,notstripped

从返回数据中我们得知了构建版本,以及得知它是一个动态链接文件

~/Desktop$nmr5
0000000000601109B__bss_start
00000000006010e0Dbuf
000000000040069dTcheck_password
0000000000601109bcompleted.6972
0000000000601060D__data_start
0000000000601060Wdata_start
00000000006010a0Ddelta
00000000004005e0tderegister_tm_clones
0000000000400650t__do_global_dtors_aux
0000000000600e18t__do_global_dtors_aux_fini_array_entry
0000000000601068D__dso_handle
0000000000600e28d_DYNAMIC
0000000000601109D_edata
0000000000601110B_end
0000000000400894T_fini
0000000000400670tframe_dummy
0000000000600e10t__frame_dummy_init_array_entry
0000000000400a80r__FRAME_END__
0000000000601000d_GLOBAL_OFFSET_TABLE_
w__gmon_start__
0000000000400500T_init
0000000000600e18t__init_array_end
0000000000600e10t__init_array_start
00000000004008a0R_IO_stdin_used
w_ITM_deregisterTMCloneTable
w_ITM_registerTMCloneTable
0000000000600e20d__JCR_END__
0000000000600e20d__JCR_LIST__
w_Jv_RegisterClasses
0000000000400890T__libc_csu_fini
0000000000400820T__libc_csu_init
U__libc_start_main@@GLIBC_2.2.5
00000000004007b6Tmain
0000000000601080Dmaster
Uprintf@@GLIBC_2.2.5
Uputs@@GLIBC_2.2.5
Urandom@@GLIBC_2.2.5
0000000000400610tregister_tm_clones
00000000004005b0T_start
Ustrcmp@@GLIBC_2.2.5
Ustrcpy@@GLIBC_2.2.5
Ustrlen@@GLIBC_2.2.5
0000000000601110D__TMC_END__

#p#

64位程序集基础

相对于X86架构,X64架构增加了扩展寄存器设置和一些额外的指令。

以下为X64增加的寄存器列表

r8, r9 , r10, r11, r12, r13, r14, r15

可以通过r8d访问r8寄存器中的低32位,通过r8w访问r8寄存器中的低16位,通过rb8访问r8寄存器中的低8位。

这样更多的RIP(指令指针)就可以直接进行访问了。

X64架构中所有的寄存器都是64位的,RIP同样也是64位,但是目前的实现方法仅是支持48位线性地址(线性地址:逻辑地址到物理地址变换之间的中间层)

除了普通的寄存器它还增加了SSE寄存器,命名为xmm8~xmm15。

如果在EAX寄存器上进行数据移动操作,他将从0一直连续到RAX寄存器的高32位。

为了达到调试程序的目的,我们将使用EDB debugger,这个调试程序类似于Windows平台下的ollydbg,上手十分容易,下面就是默认的EDB窗口。

在X64架构下参数传递与X86架构完全不同。

RDI, RSI, RDX, RCX, r8以及r9等都是通过堆栈进行参数传递。

破解入门:如何编写一个Linux 64位软件注册机

菜单栏和ollydbg一样简洁

破解入门:如何编写一个Linux 64位软件注册机

#p#

破解开始

运行我们的r5文件,返回输出如下

~/Desktop $ ./r5
Usage: ./r5 password

明文信息毕竟不太好,但是他给了我们一个需要密码的提示。我们必须弄清楚在反汇编程序中打开它会发生什么?显然它在寻找并传送一个参数到函数中。

破解入门:如何编写一个Linux 64位软件注册机

你可以清楚看到argv[1]作为参数传递给check_password()函数。

首先是有关于输入字符串的长度,字符串长度要与“this_is_not_even_interesting_its_garbage”这个字符串的长度相等。

.data:00000000006010E0;charbuf[]
.data:00000000006010E0bufdb'this_is_not_even_interesting_its_garbage',0
.data:00000000006010E0;DATAXREF:check_password+1C#o
.data:00000000006010E0;check_password+3C#o...
.data:00000000006010E0_dataends
.data:00000000006010E0
.bss:0000000000601109;===========================================================================

检测这里

call_strlen;CallProcedure
movrbx,rax
movedi,offsetbuf;“this_is_not_even_interesting_its_garbag”…
call_strlen;CallProcedure
cmprbx,rax;CompareTwoOperands
jzshortGo;JumpifZero(ZF=1)

在这之后,字符串中的数据就会被我们输入的字符串数据替换

movrax,[rbp+passcode]
movrsi,rax;src
movedi,offsetbuf;"this_is_not_even_interesting_its_garbag"...
call_strcpy;CallProcedure
mov[rbp+VarCheck],1
jmploc_400791;Jump

经过这个操作之后,程序会进入一个循环。如果指标指数delta值为0那么就会跳过这个循环体。

movzxeax,delta[rax];

破解入门:如何编写一个Linux 64位软件注册机

如果不是,将利用delta的值和其他参数在输入字符串中执行一些数学运算。

破解入门:如何编写一个Linux 64位软件注册机

用C语言来表示

x=(random()%delta[index])+1; 
delta[index]=delta[index]-x; 
var_check=var_check^(unsignedint)delta[index];

random() 并没有调用srand()进行初始化,所以我们可以轻松的进行猜测。

***,经过40轮的循环,变化的字符串如果与“this_aint_that_simple_but_good_luck_haha”相等,那么将显示“password OK”

我们可以使用以下C语言代码进行计算字符串

#include<stdio.h> 
 
unsignedchardelta[]= 
{ 
3,253,3,249,0,3,6,0,241,0, 
250,7,22,235,8,252,246,2,254,243, 
4,19,1,234,237,15,253,240,242,15, 
12,243,241,12,7,0,5,14,10,4, 
}; 
 
unsignedcharbuff[48]; 
intmain(intargc,char**argv) 
{ 
intindex=0; 
intvar_check=1; 
unsignedcharx='\x00'; 
 
strcpy(buff,"this_aint_that_simple_but_good_luck_haha"); 
 
while(var_check) 
{ 
 
index=0; 
var_check=0; 
while(index<40) 
{ 
 
if(delta[index]) 
{ 
x=(random()%delta[index])+1; 
delta[index]=delta[index]-x; 
var_check=var_check^(unsignedint)delta[index]; 
 
buff[index]=buff[index]+x; 
 
} 
 
//ifzero 
index++; 
} 
} 
 
printf("%s\n",buff); 
}

编译并运行这个程序,我们获得以下输出

“well_done_now_go_on_irc_and_ask_for_more” 
~/Desktop$./r5“well_done_now_go_on_irc_and_ask_for_more”

密码成功破解。

继续浏览有关 安全 的文章
发表评论