0x00背景

记录一下自己做出来的一道安卓的ctf题目,属于歪打正着碰进去了,应该也是很基础,因为安卓毕竟属于新型的题目。

0x01开始

首先是从题目附件处下到apk:

image-20210729101041888

然后呢,直接用jeb打开看能否反汇编源码出来:

image-20210729101241414

还都是些汇编代码,一般apk我们按照普通web项目从入口点进入,那就是s2包下的MainActivity:

image-20210729101412541

点开之后发现了sendFlag的函数,右键反编译:

image-20210729101455666

发现了这样的提示字样,可以看到已经都变成了java代码:

把关键的粘贴出来:


public class MainActivity extends AppCompatActivity {
    private Button bt;
    public static String seed;

    static {
        MainActivity.seed = "0123456789abcdefghijklmnopqrstuvwxyz";
    }

    public MainActivity() {
        super();
    }

    protected void onCreate(Bundle arg3) {
        super.onCreate(arg3);
        this.setContentView(0x7F0B001C);
        View v0 = this.findViewById(0x7F080058);
        this.bt = ((Button)v0);
        ((Button)v0).setOnClickListener(new View$OnClickListener() {
            public void onClick(View arg4) {
                Toast.makeText(MainActivity.this, "OK, You click me, but What the flag?", 1).show();
                try {
                    MainActivity.this.sendFlag();
                }
                catch(IOException v0) {
                    v0.printStackTrace();
                }
            }
        });
    }

    public void sendFlag() throws IOException {
        Runtime v0 = Runtime.getRuntime();
        String v1 = MainActivity.trans("660487647593824219489241157815659387784080160975351393328711");
        v0.exec("curl http://172.168.111.223/login.php?info = " + v1);
    }

    public static String trans(String arg7) {
        byte[] v0 = arg7.getBytes();
        StringBuffer v1 = new StringBuffer();
        int v2;
        for(v2 = 0; true; ++v2) {
            int v4 = 3;
            if(v2 >= v0.length / v4) {
                break;
            }

            int v3 = 0;
            int v5;
            for(v5 = 0; v5 < v4; ++v5) {
                v3 = (v3 + (v0[v2 * 3 + v5] - 0x30)) * 10;
            }

            v3 /= 10;
            v1.insert(v2 * 2, String.valueOf(MainActivity.seed.charAt(v3 % 36)));
            v1.insert(v2 * 2 + 1, String.valueOf(MainActivity.seed.charAt(v3 / 36)));
        }

        return v1.toString();
    }
}

通读一下代码可以发现sendflag函数里面发现可疑的v1

也就是v1所代表的值应该就是flag:

String v1 = MainActivity.trans("660487647593824219489241157815659387784080160975351393328711");

这儿跟进trans函数:

    public static String trans(String arg7) {
        byte[] v0 = arg7.getBytes();
        StringBuffer v1 = new StringBuffer();
        int v2;
        for(v2 = 0; true; ++v2) {
            int v4 = 3;
            if(v2 >= v0.length / v4) {
                break;
            }

            int v3 = 0;
            int v5;
            for(v5 = 0; v5 < v4; ++v5) {
                v3 = (v3 + (v0[v2 * 3 + v5] - 0x30)) * 10;
            }

            v3 /= 10;
            v1.insert(v2 * 2, String.valueOf(MainActivity.seed.charAt(v3 % 36)));
            v1.insert(v2 * 2 + 1, String.valueOf(MainActivity.seed.charAt(v3 / 36)));
        }

        return v1.toString();
    }
}

可以看到上面那一串不认识的十六进制字符串,就是按照这个规则最后生成一个v1.toString()返回给前面的sendFlag()函数中的v1.

那么就很清晰了:

v0.exec("curl http://172.168.111.223/login.php?info = " + v1);

最后发送出来的flag就是v1的值经过下面那一个trans函数解密。

那么我们把这个值和解密函数移到IDEA上:

image-20210729102421628

就这样写到主函数里面,然后把安卓里面的MainActivity换成自己的test类就可以了。

image-20210729102515873

运行出来加上flag{}就提交了。