黑客精神
打开界面输入注册码后弹出:
JEB分析MainActivity:onCreat 函数中出现了刚刚的已注册,通过MyApp.m来判断是否已经注册
public void onCreate(Bundle arg6) {
String v2;
super.onCreate(arg6);
this.setContentView(0x7F04001A);
String v1 = "Xman";
Log.d("com.gdufs.xman m=", v1);
this.getApplication();
int v0 = MyApp.m;
if(v0 == 0) {
v2 = "未注册";
}
else if(v0 == 1) {
v2 = "已注册";
}
else {
v2 = "已混乱";
}
this.setTitle(v1 + v2);
this.btn1 = this.findViewById(0x7F0B0054);
this.btn1.setOnClickListener(new View$OnClickListener() {
public void onClick(View arg5) {
MainActivity.this.getApplication();
if(MyApp.m == 0) {
MainActivity.this.doRegister();
}
else {
MainActivity.this.getApplication().work();
Toast.makeText(MainActivity.this.getApplicationContext(), MainActivity.workString, 0).show();
}
}
});
}
MyApp类分析:onCreate函数中调用了initSN()方法
public class MyApp extends Application {
public static int m;
static {
MyApp.m = 0;
System.loadLibrary("myjni");
}
public MyApp() {
super();
}
public native void initSN() {
}
public void onCreate() {
this.initSN();
Log.d("com.gdufs.xman m=", String.valueOf(MyApp.m));
super.onCreate();
}
public native void saveSN(String arg1) {
}
public native void work() {
}
}
RegActivity类中调用了saveSN方法,并把输入的值传到了本地
public void onClick(View arg5) {
String v0 = RegActivity.this.edit_sn.getText().toString().trim();
if(v0 == null || v0.length() == 0) {
Toast.makeText(RegActivity.this, "您的输入为空", 0).show();
}
else {
RegActivity.this.getApplication().saveSN(v0);
new AlertDialog$Builder(RegActivity.this).setTitle("回复").setMessage("您的注册码已保存").setPositiveButton("好吧", new DialogInterface$OnClickListener() {
public void onClick(DialogInterface arg2, int arg3) {
Process.killProcess(Process.myPid());
}
}).show();
}
分析so层代码
找到JNI_OnLoad注册函数
跟到n1:initSN
v2 = j_fopen("/sdcard/reg.dat", "r+"); //打开文件夹
v3 = v2;
if ( !v2 )
{
v4 = a1;
return setValue(v4, 0);
}
j_fseek(v2, 0, 2);
v5 = j_ftell(v3);
v6 = (const char *)j_malloc(v5 + 1);
if ( !v6 )
{
j_fclose(v3);
v4 = a1;
return setValue(v4, 0);
}
j_fseek(v3, 0, 0);
j_fread(v6, v5, 1, v3);
v6[v5] = 0;
if ( !j_strcmp(v6, "EoPAoY62@ElRD") ) //与字符串EoPAoY62@ElRD进行比较
{
v8 = a1;
v9 = 1;
}
else
{
v8 = a1;
v9 = 0;
}
setValue(v8, v9);
return j_fclose(v3);
}
跟到n2:saveSN
v5 = j_fopen("/sdcard/reg.dat", "w+"); //打开文件夹
if ( !v5 )
return j___android_log_print(3, "com.gdufs.xman", byte_2E5A);
strcpy(v13, "W3_arE_whO_we_ARE");
v7 = (const char *)(*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)a1 + 676))(a1, a3, 0);
v8 = v7;
v12 = j_strlen(v7);
v9 = 2016;
while ( 1 )
{
v10 = v8 - v7;
if ( v8 - v7 >= v12 )
break;
if ( v10 % 3 == 1 )
{
v9 = (v9 + 5) % 16;
v11 = v13[v9 + 1];
}
else if ( v10 % 3 == 2 )
{
v9 = (v9 + 7) % 15;
v11 = v13[v9 + 2];
}
else
{
v9 = (v9 + 3) % 13;
v11 = v13[v9 + 3];
}
*v8++ ^= v11; //if循环或者异或处理
}
j_fputs(v7, v5);
return j_fclose(v5);
}
写脚本
n1='EoPAoY62@ElRD'
data='W3_arE_whO_we_ARE'
v9=2016
flag=''
for i in range(len(n1)):
if i % 3 == 1:
v9 = (v9 +5) % 16
res = data[v9 + 1]
elif i % 3 ==2:
v9 = (v9 + 7) % 15
res = data[v9 + 2]
else:
v9 = (v9 + 3) % 13
res = data[v9 + 3]
flag+=chr(ord(n1[i])^ord(res))
print(flag)
运行
201608Am!2333
最终flag{201608Am!2333}