第一题:
解法一:反编译后,在MainActivity里找到如下代码:
String str1 = localEditText.getText().toString();
String str2 = MainActivity.this.getTableFromPic();
String str3 = MainActivity.this.getPwdFromPic();
Log.i("lil", "table:" + str2);
Log.i("lil", "pw:" + str3);
String str4 = "";
try
{
str4 = MainActivity.bytesToAliSmsCode(str2, str1.getBytes("utf-8"));
Log.i("lil", "enPassword:" + str4);
if ((str3 != null) && (!str3.equals("")) && (str3.equals(str4)))
{
MainActivity.this.showDialog();
return;
}
可知有四个字符串,str1为输入,str2从getTableFromPic()得到,str3从getPwdFromPic()得到,str4由bytesToAliSmsCode(str2, str1.getBytes("utf-8"))得到,如果str3与str4相同,则验证通过。通过逆向以上三个方法得知,str2从assets文件夹中的logo.png图片的0x15d81位置处获取0x300字节数据,作为字符串返回,str3从0x16481地址处获取0x12字节数据,作为字符串返回,bytesToAliSmsCode将str2作为表,str1每字符的ASCII值作为下标,取表中由str1映射的字符出来,组成新的字符串返回,与str4比较。因此可根据str4编写解密器,调用indexof方法在str2表中寻找str4每一个字符,记录其下标,将下标作为ASCII码转换成字符串返回,即为flag。这个解密方法在题目中已提供:
private static byte[] aliCodeToBytes(String paramString1, String paramString2)
{
byte[] arrayOfByte = new byte[paramString2.length()];
for (int i = 0; ; i++)
{
if (i >= paramString2.length())
return arrayOfByte;
arrayOfByte[i] = ((byte)paramString1.indexOf(paramString2.charAt(i)));
}
}
解法二:
不逆向上述三个方法,观察到如下代码:
Log.i("lil", "table:" + str2);
Log.i("lil", "pw:" + str3);
Log.i("lil", "enPassword:" + str4);
可知str2、str3与str4已用logcat打印出来,因此可以考虑用黑盒法猜测str1。
logcat打印str3结果如下:
pw:义弓么丸广之
根据题目描述,猜测答案是由数字组成,因此输入"0123456789",得到如下打印:
enPassword:丸么广亡门义之尸弓己
观察到pw打印的每一个字在enPassword里都存在,因此考虑数字与打印结果有一一对应关系,根据打印结果的排列,猜测答案为581026。
输入后得知破解成功。
第二题:
反编译看到如下:
String str = MainActivity.this.inputCode.getText().toString();
if (MainActivity.this.securityCheck(str))
{
Intent localIntent = new Intent(MainActivity.this, ResultActivity.class);
MainActivity.this.startActivity(localIntent);
return;
}
Toast.makeText(MainActivity.this.getApplicationContext(), "验证码校验失败", 0).show();
}
得知调用securityCheck方法对输入的字符串进行校验,返回true则校验成功,该方法在libcrackme.so里,因此用ida对其逆向。
在逆向过程中发现了该方法,部分关键代码如下:
.text:000012A8 loc_12A8 ; CODE XREF: Java_com_yaotong_crackme_MainActivity_securityCheck+120j
.text:000012A8 LDRB R3, [R2]
.text:000012AC LDRB R1, [R0]
.text:000012B0 CMP R3, R1
.text:000012B4 BNE loc_12D0
.text:000012B8 ADD R2, R2, #1
.text:000012BC ADD R0, R0, #1
.text:000012C0 MOV R1, #1
.text:000012C4 CMP R3, #0
.text:000012C8 BNE loc_12A8
.text:000012CC B loc_12D4
.text:000012D0 ; ---------------------------------------------------------------------------
.text:000012D0
.text:000012D0 loc_12D0 ; CODE XREF: Java_com_yaotong_crackme_MainActivity_securityCheck+10Cj
.text:000012D0 MOV R1, #0
.text:000012D4
.text:000012D4 loc_12D4 ; CODE XREF: Java_com_yaotong_crackme_MainActivity_securityCheck+124j
.text:000012D4 MOV R0, R1
.text:000012D8 ADD SP, SP, #8
.text:000012DC LDMFD SP!, {R4-R7,R11,PC}
可知程序用一个循环比较输入字符串与一个特定的字符串,如果相同则返回1,不相同则返回0。
逆向得知此字符串偏移量如下:
.data:0000628C off_628C DCD aWojiushidaan
尝试输入wojiushidaan后破解失败,考虑可能程序在运行时动态修改了值,因此必须调试查看。
但程序存在Anti-code,开了一个线程用以检测本程序是否正在被调试,因此将其susppend,即可继续调试。
在调试过程中,找到此字符串为:
aiyou,bucuoo
输入后即破解成功。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)