apk分析
分析所有掌握的检材,找到报案人描述的加密勒索apk程序,分析并回答下列问题
46.恶意APK程序的包名为
cn.forensix.changancup
47.APK调用的权限包括
READ_EXTERNAL_STORAGE;WRITE_EXTERNAL_STORAGE
48.解锁第一关所使用的FLAG2值为(FLAG为8位字符串,如需在apk中输入FLAG,请输入完整内容,如输入"FLAG9:QWERT123")
脱壳后反编译,搜索文本
FLAG
MATSFRKG
49.解锁第二关所使用的FLAG3值为(FLAG为8位字符串,如需在apk中输入FLAG,请输入完整内容,如输入"FLAG9:QWERT123")
上面代码中对FLAG3的判断条件为
i2 & 2
privatevoidOooO00o(){int i2 =App.OooO0OO.getInt("unlocked",0);if((i2 &4)!=0){this.OooO0OO.setText("哎呀,第三关都通过了,恭喜恭喜,现在你的手机已获得自由!");this.OooO0Oo.setVisibility(8);this.OooO0o0.setVisibility(8);}elseif((i2 &2)!=0){this.OooO0OO.setText("你是怎么通过第二关的???不过还有第三关,现在你手机里任何文档,压缩包,图片,视频都已被加密,请再次联系QQ:90001234进行解密");this.OooO0Oo.setOnClickListener(this);this.OooO0o0.setHint("输入解密文件的key");this.OooO0o0.setText("");}elseif((i2 &1)!=0){this.OooO0OO.setText("居然通过了第一关,不过还有第二关在等着你,现在你的手机在接下来的时间,会每隔一段时间关闭屏幕,请再次联系QQ:90001234进行解除,期间请勿尝试任何手段破解,否则将触发自毁程序");this.OooO0Oo.setOnClickListener(this);this.OooO0o0.setHint("FLAG3:XXXXXXXX");this.OooO0o0.setText("");}else{this.OooO0OO.setText("恭喜,你的手机已被锁,请联系QQ:90001234进行解决,期间请勿尝试任何手段破解,否则将触发自毁程序");this.OooO0Oo.setOnClickListener(this);this.OooO0o0.setHint("FLAG2:XXXXXXXX");this.OooO0o0.setText("");}}
查看
else if
elseif(App.OooO0O0.OooO0oo.equals(this.OooO0o0.getText().toString())&&App.OooO0OO.edit().putInt("unlocked",App.OooO0OO.getInt("unlocked",0)|2).commit()){StringBuilderOooO0OO2=C0253o0000Oo.OooO0OO(App.OooO0OO.getString("flag16_tkey",""));OooO0OO2.append(App.OooO0O0.OooO0oo);
e
q
u
a
l
s
(
t
h
i
s
.
O
o
o
O
0
o
0.
g
e
t
T
e
x
t
(
)
.
t
o
S
t
r
i
n
g
(
)
equals(this.OooO0o0.getText().toString()
equals(this.OooO0o0.getText().toString()
将输入的值转换成字符串与前面的
App.OooO0O0.OooO0oo
进行比对,查找
OooO0O0
定义
this.OooO0oo=newString(decrypt(OooO0O0.OooO0O0("ffd4d7459ad24cd035611b014a2cccac")));try{Cipher instance =Cipher.getInstance("AES/GCM/NoPadding");if(TextUtils.isEmpty(OooO0OO.getString("t_key",""))){
instance.init(1,OooO0oO());byte[] bArr =newbyte[16];newSecureRandom().nextBytes(bArr);init(bArr);if(OooO0OO.edit().putString("iv",OooO0O0.OooO00o(instance.getIV())).commit()&&OooO0OO.edit().putString("t_key",OooO0O0.OooO00o(instance.doFinal(bArr))).commit()){System.out.println("init key ok");}}elseif(Build.VERSION.SDK_INT>=19){
instance.init(2,OooO0o(),newGCMParameterSpec(128,OooO0O0.OooO0O0(OooO0OO.getString("iv",""))));init(instance.doFinal(OooO0O0.OooO0O0(OooO0OO.getString("t_key",""))));}else{thrownewRuntimeException("todo cipher");}}catch(Exception unused){}
查找OooO0O0
publicstaticbyte[]OooO0O0(String str){int length = str.length()/2;byte[] bArr =newbyte[length];for(int i2 =0; i2 < length; i2++){int i3 = i2 *2;
bArr[i2]=(byte)Integer.parseInt(str.substring(i3, i3 +2),16);}return bArr;}
查找decrypt方法
publicnativebyte[]decrypt(byte[] bArr);
调用了libcipher.so进行解密对输入值进行比较
static {
System.loadLibrary("cipher");
}
查看一下
OooO0O0
用例,发现数组转换代码,直接复制粘贴
publicstaticbyte[]OooO0O0(String str){int length = str.length()/2;byte[] bArr =newbyte[length];for(int i2 =0; i2 < length; i2++){int i3 = i2 *2;
bArr[i2]=(byte)Integer.parseInt(str.substring(i3, i3 +2),16);}return bArr;}
思路:提取出所需函数、so文件至新项目,直接执行
提取对应的so文件到项目中
使用AndroidStudio对函数进行复现
packagecn.forensix.cab;importandroid.app.Application;publicclassAppextendsApplication{static{System.loadLibrary("cipher");}publicnativebyte[]decrypt(byte[] bArr);publicvoidmain(){String out =newString(decrypt(OooO0O0("ffd4d7459ad24cd035611b014a2cccac")));//直接输出值而非调用,此处来源 this.OooO0oo = new String(decrypt(OooO0O0.OooO0O0("ffd4d7459ad24cd035611b014a2cccac")));System.out.println("ocipher:"+ out);}//调用OooO0O0数组转换代码publicstaticbyte[]OooO0O0(String str){int length = str.length()/2;byte[] bArr =newbyte[length];for(int i =0; i < length; i++){int i2 = i *2;
bArr[i2]=(byte)Integer.parseInt(str.substring(i2, i2 +2),16);}return bArr;}}
在Logcat中可以找到FLAG3
TDQ2UWP9
50.解锁第三关所需的KEY值由ASCII可显示字符组成,请请分析获取该KEY值
第三关要求输入解密文件的key,不再是
FLAGx:
的形式
同样在App.java中可以看到key的定义
字符串长度为
24
publicbooleanOooO0O0(String str){if(str.length()!=24){returnfalse;}
分为长度为
6
的四组字符串
long[] jArr =newlong[6];for(int i2 =0; i2 < str.length()/4; i2++){int i3 = i2 *4;
jArr[i2]=(long)(str.charAt(i3)<<16);
jArr[i2]= jArr[i2]|((long)(str.charAt(i3 +1)<<'\b'));
jArr[i2]= jArr[i2]|((long)(str.charAt(i3 +2)<<24));
jArr[i2]=((long) str.charAt(i3 +3))| jArr[i2];PrintStream printStream =System.out;
printStream.println("buildKey:i:"+ i2 +",value:"+ jArr[i2]);}
可以学习复盘视频解决该问题
复盘
其他参赛选手的脚本也能解决
java脚本来源WXjzcccc的博客:https://blog.csdn.net/WXjzcccc/article/details/127609236
ps:不妥请马上联系我删除
packagecn.forensix.cab;/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/publicclassTest{staticint[]OooO0oO={1197727163,1106668241,312918615,1828680913,1668105995,1728985987};publicstaticlong[]OooO(long j,long j2){if(j ==0){returnnewlong[]{0,1};}long[]OooO=OooO(j2 % j, j);returnnewlong[]{((j2 / j)*OooO[0])+OooO[1],OooO[0]};}publicstaticvoidmain(String[] args){String res ="";for(int i =0; i <6; i++){//4层循环遍历4位字符串for(int a1 =33; a1 <127; a1++){for(int a2 =33; a2 <127; a2++){for(int a3 =33; a3 <127; a3++){for(int a4 =33; a4 <127; a4++){long tmp =(long)(a1 <<16);
tmp = tmp |((long)(a2 <<'\b'));
tmp = tmp |((long)(a3 <<24));
tmp =((long) a4)| tmp;if(((OooO(tmp,0x100000000L)[0]%0x100000000L)+0x100000000L)%0x100000000L ==((long)OooO0oO[i])){
res +=(char)a1;
res +=(char)a2;
res +=(char)a3;
res +=(char)a4;//获取到当前密码后,跳出4层循环
a1 = a2 = a3 = a4 =128;}}}}}}System.out.println(res);}}
C++脚本来源4dBmk的博客:https://blog.mstg.top/archives/506
ps:不妥请马上联系我删除
#include<iostream>#include<string>#include<thread>#include<cstdint>#include<map>#include<vector>unsignedintcalc(unsignedint i){auto p = reinterpret_cast<unsignedchar*>(&i);unsignedint ret =0;
ret =(long)(p[0]<<16);
ret = ret |((long)(p[1]<<'\b'));
ret = ret |((long)(p[2]<<24));
ret =((long)p[3])| ret;return ret;}
std::pair<int64_t,int64_t>OooO(int64_t j,int64_t j2){if(j ==0){return{0,1};}auto ret =OooO(j2 % j, j);return{((j2 / j)* ret.first)+ ret.second, ret.first };}voidrun_range(unsignedint start,unsignedint end){staticconstuint32_t oooooo[]={1197727163,1106668241,312918615,1828680913,1668105995,1728985987};for(unsignedint i = start; i < end;++i){auto ret =calc(i);auto ret2 =((OooO(ret,4294967296L).first %4294967296L)+4294967296L)%4294967296L;for(int j =0; j <6;++j){if(oooooo[j]== ret2){
std::cout << j <<":"<< oooooo[j]<<":"<< std::string(reinterpret_cast<constchar*>(&i),4)<< std::endl;break;}}}}intmain(){
std::cout <<"start"<< std::endl;
std::vector<std::thread> thds;for(uint32_t i =0; i <16;++i){auto start =0x10000000* i -1;auto end =0x10000000*(i +1)-1;
thds.emplace_back([start, end]{run_range(start, end);});}for(auto& thd : thds){
thd.join();}return0;}
按照描述排序
a_asd./1imc2)dd1234]_+=+
版权归原作者 p1ant731 所有, 如有侵权,请联系我们删除。