从bLaCk-eye的网站上down到的,觉得挺有用的。网址是http://www.secretashell.com/cryptocrk/,这里东西不少,推荐去看看。
MIARCL是当前使用比较广泛的基于公钥加密算法保护实现的大数库之一,特别在各种算法Crackme中。目前为止还没有发现使用该库的商业软件,因为MIRACL用于商业目的的话需要交纳一笔昂贵的授权费——1000$。所以这里介绍的这个技巧只能对你破解各种算法Crackme起到一点帮助。
这个技巧是怎么来的呢?
我们知道,MIRACL有一个十分有用的特性:它可以让你十分方便的定位程序运行过程中出错的函数,MIRACL的文档是这样说的:
”初始化函数mirsys运行的同时也会初始化集成在MIRACL库中的错误跟踪系统。这样,无论何时只要函数调用序列中的任何一个函数发生错误都会被检测到,包括错误本身。一个典型的错误信息如下:
MIRACL error from routine powltr
called from isprime
called from your program
Raising integer to a negative power
这些错误报告在开发过程中对我们调试有很大的帮助。与之相关的一个常量是TRACER,默认是OFF,如果将它改为ON,程序运行过程中将会把错误信息打印到电脑屏幕上。”
上面这些信息对我们有什么帮助呢?
MIRACL能确切知道哪个函数出错是因为它对每个函数定义了一个特定的常量作为标识符,这些信息是从MIRACL源代码里发现的。下面是MrArth3.c里的一段代码:
void power(_MIPD_ big x,long n,big z,big w)
{ /* raise big number to int power w=x^n *
* (mod z if z and w distinct) */
mr_small norm;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
copy(x,mr_mip->w5);
zero(w);
if(mr_mip->ERNUM || size(mr_mip->w5)==0) return;
convert(_MIPP_ 1,w);
if (n==0L) return;
MR_IN(17)
if (n<0L)
{
mr_berror(_MIPP_ MR_ERR_NEG_POWER);
MR_OUT
return;
}
//rest of the code from file
}
注意粗体字显示的那段代码。我们可以看到,这条代码不在任何一个条件编译代码段内,这就意味着无论你用何种选项编译MIRACL,MR_IN(17)都会在最终生成库文件里面。
将这段代码反汇编的结果是:
mov dword ptr [esi+eax*4+20h], 11h
11h的十进制正是17。
现在你明白如何去识别MIRACL库的函数了吧:调试时跟进有疑问的CALL,搜索下面形式的指令:
mov dword ptr [esi+eax*4+20h], XXh
在你自己的函数特征值表中查找XX,或者直接对照我在后面列出的那个表。
有了这个所有函数特征值对应表后我们就可以十分轻松的识别MIRACL里的所有函数。这个方法的优点就是每个函数对应的特征值一般不会由于库版本的升级而发生变化,因此可以比较放心的使用。缺点呢就是你必须自己动手去一个一个函数地去识别。对于这点一个好的解决办法就是编写一个IDA的脚本,自动搜索那些的指令并根据特征值修改函数名。
附表:
MIRACL MAGIC NUMBERS TABLE:
by bLaCk-eye
from an original ideea by bF!^k23
NUMBER OF FUNCTIONS: 08Eh
Innum equ 01h
Otnum equ 02h
Jack equ 03h
normalise equ 04h
multiply equ 05h
divide equ 06h
incr equ 07h
decr equ 08h
premult equ 09h
subdiv equ 0Ah
fdsize equ 0Bh
egcd equ 0Ch
cbase equ 0Dh
cinnum equ 0Eh
cotnum equ 0Fh
nroot equ 10h
power equ 11h
powmod equ 12h
bigdig equ 13h
bigrand equ 14h
nxprime equ 15h
isprime equ 16h
mirvar equ 17h
mad equ 18h
multi_inverse equ 19h
putdig equ 1Ah
add equ 1Bh
subtract equ 1Ch
mirsys equ 1Dh
xgcd equ 1Eh
fpack equ 1Fh
dconv equ 20h
mr_shift equ 21h
mround equ 22h
fmul equ 23h
fdiv equ 24h
fadd equ 25h
fsub equ 26h
fcomp equ 27h
fconv equ 28h
frecip equ 29h
fpmul equ 2Ah
fincr equ 2Bh
;null entry
ftrunc equ 2Dh
frand equ 2Eh
sftbit equ 2Fh
build equ 30h
logb2 equ 31h
expint equ 32h
fpower equ 33h
froot equ 34h
fpi equ 35h
fexp equ 36h
flog equ 37h
fpowf equ 38h
ftan equ 39h
fatan equ 3Ah
fsin equ 3Bh
fasin equ 3Ch
fcos equ 3Dh
facos equ 3Eh
ftanh equ 3Fh
fatanh equ 40h
fsinh equ 41h
fasinh equ 42h
fcosh equ 43h
facosh equ 44h
flop equ 45h
gprime equ 46h
powltr equ 47h
fft_mult equ 48h
crt_init equ 49h
crt equ 4Ah
otstr equ 4Bh
instr equ 4Ch
cotstr equ 4Dh
cinstr equ 4Eh
powmod2 equ 4Fh
prepare_monty equ 50h
nres equ 51h
redc equ 52h
nres_modmult equ 53h
nres_powmod equ 54h
nres_moddiv equ 55h
nres_powltr equ 56h
divisible equ 57h
remain equ 58h
fmodulo equ 59h
nres_modadd equ 5Ah
nres_modsub equ 5Bh
nres_negate equ 5Ch
ecurve_init equ 5Dh
ecurve_add equ 5Eh
ecurve_mult equ 5Fh
epoint_init equ 60h
epoint_set equ 61h
epoint_get equ 62h
nres_powmod2 equ 63h
nres_sqroot equ 64h
sqroot equ 65h
nres_premult equ 66h
ecurve_mult2 equ 67h
ecurve_sub equ 68h
trial_division equ 69h
nxsafeprime equ 6Ah
nres_lucas equ 6Bh
lucas equ 6Ch
brick_init equ 6Dh
pow_brick equ 6Eh
set_user_function equ 6Fh
nres_powmodn equ 70h
powmodn equ 71h
ecurve_multn equ 72h
ebrick_init equ 73h
mul_brick equ 74h
epoint_norm equ 75h
nres_multi_inverse equ 76h
;null entry
nres_dotprod equ 78h
epoint_negate equ 79h
ecurve_multi_add equ 7Ah
ecurve2_init equ 7Bh
epoint2_init equ 7Ch
epoint2_set equ 7Dh
epoint2_norm equ 7Eh
epoint2_get equ 7Fh
epoint2_comp equ 80h
ecurve2_add equ 81h
epoint2_negate equ 82h
ecurve2_sub equ 83h
ecurve2_multi_add equ 84h
ecurve2_mult equ 85h
ecurve2_multn equ 86h
ecurve2_mult2 equ 87h
ebrick2_init equ 88h
mul2_brick equ 89h
prepare_basis equ 8Ah
strong_bigrand equ 8Bh
bytes_to_big equ 8Ch
big_to_bytes equ 8Dh
set_io_buffer_size equ 8Eh