一枚KeyGenMe分析
来源:互联网 发布:元贝驾考电脑版软件 编辑:程序博客网 时间:2024/05/01 15:37
一枚KeyGenMe分析
前言
玩CM的人好像很少,大家都缺乏热情,小弟在此分析一枚,错误之处望各位大侠不吝指正。
“元旦佳节,难得有闲情逸致。品一杯香茗,看IDA中的汇编代码。”
虽说是迟到的祝福,但这里还是先祝各位朋友元旦快乐,愿大家的技术蒸蒸日上,身体棒,棒,棒!在逆向这条荆棘密布的道路上,难免遇到各种各样的困难,有的甚至是看似不可逾越的鸿沟。但话又说回来,其实逆向这个领域,很多技术是相通的,思维方式更是相通的。
网上的资料并不少,教程和文章都很多,少的就是大家对一些新问题的思考,对一些知识的灵活运用和融会贯通。
初探加壳so
一般来说,我们从java层入手,在跟踪某一个关键函数或者一个关键变量的时候,会跟到一个native的函数里,这个时候就需要进入深邃的so。或许很多人会害怕so加壳,觉得那么遥不可及。我们来揭开加壳后so的神秘面纱,让大家对so加壳不再畏惧。
打开IDA定位到关键函数后:
如图,指令都被抹掉了,关键的函数完完全全被“清空”。
其他函数也一并被清空:
卸下加壳so的外衣
尽管IDA加载的so里面的指令都被清空了,但是有一条不变的宗旨。那就是这些代码在执行之前肯定要解密的,解密的时候那就肯定在内存中,既然在内存中,我们就可以把它拿出来。
在关键函数段首下好断点:
IDA附加程序,出现same则点击same对话框。接下来需要让程序断在我们的断点处,代码已经解密出来了:
接下来用Ctrl+S 来定位一下该so在内存中的位置,用以下IDC脚本dump出来即可:
auto fp, SoAddress;fp = fopen("D:\\unpack.so", "wb");for ( SoAddress=0x51F6546C; SoAddress< 0x51F6B7B8; SoAddress++ )fputc(Byte(SoAddress), fp);
脱壳前后对比
左边为加壳后的指令,都被抹去
右边为脱壳后的指令,全部恢复
细心的读者,肯定会发现,这和脱dex很相似,是的,这就是脱dex的方法在脱so壳上的再利用。
So里面遨游
在check函数里面:
可以看到最后对比的字符串为:XVccAwVbVQQE
我们从最后开始往前推到。
转换成相对应的Hex如下:
0x58 0x56 0x63 0x63
0x41 0x77 0x56 0x62
0x56 0x51 0x51 0x45
这些Hex的值怎么算出来的呢?继续往前看:
在base64encode函数中:
一共12个值,通过num2base64char函数,循环3次,每次4个值。
进入num2base64char函数里看算法:
贴一段转换后的java代码:
public static int NumToChar(int a1){
{
int v2 ;
if ( a1 <= 0x19 ) //65到90
return (a1 + 65);
if ( a1 <= 0x33 )//
return (a1 + 71);//71到122
if ( a1 <= 0x3D )//61-4
return (a1 - 4);
v2 = 43;
if ( a1 != 62 )
{
if ( a1 == 63 )
{
v2 = 47;
}
else if ( a1 == 64 )
{
v2 = 61;
}
}
return v2;
}
根据这段算法逆推出Numtochar之前的Hex为:
0x17 0x15 0x1c 0x1c
0x00 0x30 0x15 0x1b
0x15 0x10 0x10 0x04
继续向前看,找出这12个Hex的值是如何来的:
图中红框的函数为关键函数,进去看一下:
传入3个参数,生成了4个结果。所以之前的12个Hex的值应该是3组3位的Hex值生成的,根据算法,解密程序如下:
int x ,y ,z ,four1,four2,four3,four4; for(x=0;x<=0xff;x++){ for(y=0;y<=0xff;y++){ for(z=0;z<=0xff;z++){ four1 = x>>2; four2 = (16 * x & 0x30) + (y >> 4); four3 = (4 * y & 0x3C) + (z >> 6); four4 = z & 0x3F; if(four1==0x15 && four2==0x10 && four3==0x10 && four4==0x04){ System.out.println("X:0x"+Integer.toHexString(x)+" Y:0x"+Integer.toHexString(y)+" Z:0x"+Integer.toHexString(z)); } } } }
得出3组3位的Hex值如下:
0x5d 0x57 0x1c
0x03 0x05 0x5b
0x55 0x04 0x04
再往前就是java层了:只要传入的字符串为以下Hex则成功:
16进制:5d 57 1c 03 05 5b 55 04 04
| || |
\ /
\/
JAVA层
JAVA层的加密函数为:
public static String Encrpt(String arg9, String arg10) { String v0_2; String v1 = null; if(arg9 != null && arg10 != null) { try { char[] v2 = arg10.toCharArray(); char[] v3 = arg9.toCharArray(); int v4 = v3.length; //v4 =9 int v5 = v2.length; char[] v6 = new char[v4]; int v0_1; for(v0_1 = 0; v0_1 < v4; ++v0_1) { System.out.println((int)(v3[v0_1])+" ^ "+(int)v2[v0_1 % v5]); v6[v0_1] = ((char)(v3[v0_1] ^ v2[v0_1 % v5])); } v0_2 = new String(v6); } catch(Exception v0) { v0.printStackTrace(); v0_2 = v1; } } else { v0_2 = v1; } return v0_2; } public static String toHexString(String s) { String str = ""; for (int i = 0; i < s.length(); i++) { int ch = (int) s.charAt(i); String s4 = Integer.toHexString(ch); System.out.println((i+1)+": 0x"+s4); str = str + s4; } return str; }
运算都是异或加密,逆运算就是结果与key再异或回来,而key在Java层已经可以知道,为”52pojie”,所以异或回来的答案如下:
Answer:104 101 108 108 111 50 48 49 54
最后再查一下ASCII码表得出答案为:hello2016
验证一下:
总结
希望通过对这篇文章阅读,你已经对so不再恐惧了。再次祝大家2016年有新的收获!
2016年元旦
By Ericky
- 一枚KeyGenMe分析
- ASA's KeygenMe#2
- Souhail's Keygenme
- keygenning for deurus KeygenMe#02
- Blue Indian's Puzzler Keygenme
- 一枚Android拦截马简要分析
- quake2源码分析(一)
- AppFuseXML文件分析(一)
- SPS2007数据结构分析一
- MTD源代码分析(一)
- kdb代码分析(一)
- block cleanout分析(一)
- PetStore1.3分析 一
- 经典批处理分析(一)
- eMule源代码分析(一)
- P2psim 源代码分析(一)
- OpenLayers项目分析一
- Tomcat源码分析(一)
- 绑定事件监听器
- 将数组作为参数传递(C# 编程指南)
- 欢迎使用CSDN-markdown编辑器
- 降维(二)----Laplacian Eigenmaps
- Redis非常重要的安全性配置
- 一枚KeyGenMe分析
- No result defined for action com.buaa.spring_test.action.TestAction and result input
- matlab显示的图片,手动保存时四周有白边
- (数据结构)排序--直接插入排序
- linux下gcc/g++的命令和使用详解
- Install python opencv on mac
- 使用 ref 和 out 传递数组(C# 编程指南)
- 【Android 界面效果1】ViewPager多页面滑动切换以及动画效果
- 【Android 界面效果2】ViewFlipper实现滑动翻页