这是一道纯算法还原题

1. apk安装到手机,提示输入flag,看来输入就是flag

2. jadx 打开apk查看

        this.button.setOnClickListener(new View.OnClickListener() { // from class: com.example.test.ctf03.MainActivity.1
@Override // android.view.View.OnClickListener
public void onClick(View v) {
String str = MainActivity.this.pwd.getText().toString();
int result = JNI.getResult(str);
MainActivity.this.Show(result);
}
});

JNI.java

public class JNI {
public static native int getResult(String str); static {
System.loadLibrary("Native");
}
}

3. IDA打开 libNative.so 看看

bool __fastcall Java_com_example_test_ctf03_JNI_getResult(JNIEnv *env, jclass a2, jstring str)
{
int v3; // r4
const char *str_chars; // r8
char *v5; // r6
char *v6; // r4
char *v7; // r5
int i; // r0
int j; // r0 v3 = 0;
str_chars = (*env)->GetStringUTFChars(env, str, 0);
if ( strlen(str_chars) == 15 )
{
v5 = (char *)malloc(1u);
v6 = (char *)malloc(1u);
v7 = (char *)malloc(1u);
Init(v5, v6, v7, str_chars, 15);
if ( !First(v5) )
return 0;
for ( i = 0; i != 4; ++i )
v6[i] ^= v5[i];
if ( !strcmp(v6, a5) )
{
for ( j = 0; j != 4; ++j )
v7[j] ^= v6[j];
return strcmp(v7, "AFBo}") == 0;
}
else
{
return 0;
}
}
return v3;
}

先看一下Init函数在干什么

int __fastcall Init(int result, char *a2, char *a3, const char *str_chars, int len)
{
int v5; // r5
int v6; // r10
int v7; // r6 if ( len < 1 )
{
v6 = 0;
}
else
{
v5 = 0;
v6 = 0;
do
{
v7 = v5 % 3;
if ( v5 % 3 == 2 )
{
a3[v5 / 3u] = str_chars[v5];
}
else if ( v7 == 1 )
{
a2[v5 / 3u] = str_chars[v5];
}
else if ( !v7 )
{
++v6;
*(_BYTE *)(result + v5 / 3u) = str_chars[v5];
}
++v5;
}
while ( len != v5 );
}
*(_BYTE *)(result + v6) = 0;
a2[v6] = 0;
a3[v6] = 0;
return result;
}

通过分析可知,该函数将字符串分为了三分,第一个字符给a1,第二个给a2,第三个给a3,第四个给a1,这样循环下去

再看First函数
bool __fastcall First(char *a1)
{
int i; // r1 for ( i = 0; i != 4; ++i )
a1[i] = (2 * a1[i]) ^ 0x80;
return strcmp(a1, "LN^dl") == 0;
}

这里是 拿着a对应的字符做个计算然后取和一个常量比较,这里可以倒推出a1的值,对应python

def first():
b = "LN^dl"
a1 = ''
for i in range(0, 4):
print(i)
a1 += (chr(int((ord(b[i])^0x80)/2)))
a1 += 'l'
print(a1) #得到 fgorl

注意这里得到了a1原来的值,但是这里a1已经被改了,值为"LN^dl", 我就在这里被坑到了

first函数过了之后,v6 做了一些计算,然后又和一个常量比较,那么又可以用上面的方法取干活
    for ( i = 0; i != 4; ++i )
v6[i] ^= v5[i];
if ( !strcmp(v6, a5) ){
......
}

对应python

def second():
a5 = [ord(' '), ord('5'), ord('-'), 0x16, ord('a')]
# v5 = [ord('f'), ord('g'), ord('o'), ord('r'), ord('l')]
v5 = [ord('L'), ord('N'), ord('^'), ord('d'), ord('l')]
v6 = ""
for i in range(0, 4):
t = v5[i]^a5[i]
v6 += (chr(t))
v6 += 'a'
print(v6) # 得到 l{sra

最后v7 也是一个套路,这里就直接给还原的代码了

def third():
a6 = [ord('A'), ord('F'), ord('B'), ord('o'), ord('}')]
v6 = [ord(' '), ord('5'), ord('-'), 0x16, ord('a')]
v7 = ''
for i in range(0, 4):
t = v6[i]^a6[i]
v7 += (chr(t))
v7 += '}'
print(v7) # 得到 asoy}

最后把三个值拼起来,也就是最上面分析的那个循环赋值的逻辑,这里是还原算法

s1 = 'fgorl'
s2 = 'l{sra'
s3 = 'asoy}'
flag = ''
for i in range(5):
flag += s1[i] + s2[i] + s3[i]
print(flag) # 得到 flag{sosorryla}

【Android 逆向】【攻防世界】android2.0的更多相关文章

  1. 逆向-攻防世界-crackme

    查壳,nSpack壳,直接用软件脱壳,IDA载入程序. 很明显,就是将402130的数据和输入的数据进行异或,判断是否等于402150处的数据.dwrd占4字节. 这道题主要记录一下刚学到的,直接在I ...

  2. 逆向-攻防世界-maze

    题目提示是走迷宫. IDA载入程序分析. 输入字符长度必须是24,开头必须是nctf{,结尾必须是}.在125处按R就可以变成字符. sub_400650和sub_400660是关键函数,分析sub_ ...

  3. 逆向-攻防世界-CSAW2013Reversing2

    运行程序乱码,OD载入搜索字符串,断电到弹窗Flag附近. 发现跳过00B61000函数,弹窗乱码,我们试试调用00B61000函数.将00B61094的指令修改为JE SHORT 00B6109b. ...

  4. 逆向-攻防世界-logmein

    iDA载入程序,shift+F12查看关键字符串,找到双击来到所在地址,进入函数 然后进入主函数, 经过分析,可以得出:输入的字符要等于  经过处理的v7和v8的异或.v8很明显,但是v7是怎么回事呢 ...

  5. 逆向-攻防世界-no-strings-attached

    看题目就知道查找不到关键字符串,为防止踩坑,strings命令查看,没有找到有用的字符串.IDA载入程序查找入口函数, main函数中有4个函数,经过分析判断authenticate()为关键函数,跟 ...

  6. 攻防世界逆向——game

    攻防世界逆向:game wp 攻防世界逆向新手区的一道题目. 是一道windows的creak,动态调试打开是这样的: 题目说明是让屏幕上所有的图像都亮之后,会出现flag,看来应该是可以玩出来的. ...

  7. [转]Android逆向之动态调试总结

    一.在SO中关键函数上下断点 刚学逆向调试时.大多都满足于在SO中某关键函数上下断点.然后通过操作应用程序,去触发这个断点,然后进行调试 详细的步骤可以参见非虫大大的<Android软件安全与逆 ...

  8. 攻防世界 reverse evil

    这是2017 ddctf的一道逆向题, 挑战:<恶意软件分析> 赛题背景: 员工小A收到了一封邮件,带一个文档附件,小A随手打开了附件.随后IT部门发现小A的电脑发出了异常网络访问请求,进 ...

  9. 攻防世界 reverse 进阶 APK-逆向2

    APK-逆向2 Hack-you-2014 (看名以为是安卓逆向呢0.0,搞错了吧) 程序是.net写的,直接祭出神器dnSpy 1 using System; 2 using System.Diag ...

  10. Android trap攻防思路整理

    Android trap攻防                                                                      图/文 h_one 0x01 反 ...

随机推荐

  1. [粘贴]TiFlash

    TiFlash 是 TiDB HTAP 形态的关键组件,它是 TiKV 的列存扩展,在提供了良好的隔离性的同时,也兼顾了强一致性.列存副本通过 Raft Learner 协议异步复制,但是在读取的时候 ...

  2. 申威3231_SPECJVM2008的测试结果与信创服务器对比验证

    申威3231_SPECJVM2008的测试结果与信创服务器对比验证 背景 周六找同事将在公司里的机器进行了开机. 然后验证了config.guess和config.sub 的确是可以通过复制/usr ...

  3. [转帖]Centos7 nginx访问日志文件割接

    一.yum安装nginx 二.各文件路径( /etc/nginx/nginx.conf) 1.访问日志路径:access_log /var/log/nginx/access.log main; 2.p ...

  4. Promise的异常穿透和中断Promise的链式请求

    1.Promise的异常穿透 1==>当你使用Promise的then,进行链式调用的时候,可以在最后指定失败的回调 2==>前面任何操作出现了异常,都会传递到最后失败的回调中进行处理: ...

  5. Gorm实战,轻松掌握数据库增删改查技巧!

    Gorm实战,轻松掌握数据库增删改查技巧! CRUD通常指数据库的增删改查操作,本文详细介绍了如何使用GORM实现创建.查询.更新和删除操作. 目录 Gorm实战,轻松掌握数据库增删改查技巧! 一.C ...

  6. github 2fa中国认证及TOTP App

    Because of your contributions on GitHub, two-factor authentication will be required for your account ...

  7. 离线下载和安装UWP(windows应用商店)软件

    离线下载uwp安装包 打开商店,然后搜索您要的应用程序名称,进入应用界面 点击 分享按钮,在弹出窗口中选择[复制链接] 把链接粘贴到:https://store.rg-adguard.net/ 默认选 ...

  8. 复原docker中容器的启动命令

    复原 docker 容器的启动命令 前言 查看 docker 容器的启动命令 参考 复原 docker 容器的启动命令 前言 不规范的操作,在启动 docker 容器,没有留命令脚本,或者没有使用 d ...

  9. C++ Boost库 操作字符串与正则

    字符串的查找与替换一直是C++的若是,运用Boost这个准标准库,将可以很好的弥补C++的不足,使针对字符串的操作更加容易. 字符串格式转换: #include <iostream> #i ...

  10. 遥感图像处理笔记之【Land use/Land cover classification with Deep Learning】

    遥感图像处理学习(1) 前言 遥感图像处理方向的学习者可以参考或者复刻 本文初编辑于2023年12月14日CSDN平台 2024年1月24日搬运至本人博客园平台 文章标题:Land use/Land ...