NewStarCTF2023公开赛week3安卓wp

admin 2023年10月26日02:31:52评论22 views字数 4029阅读13分25秒阅读模式

NewStarCTF2023公开赛week3安卓wp

runfaraway

放进jadx,发现是传入字符串和key(固定),通过调用native层的encode方法,判断是否正确。NewStarCTF2023公开赛week3安卓wp

将so放入ida分析,可以看到,这v7是字符串(图没截全),v8是key,经过算法处理后,再用test函数处理v7,得到的值与下面的一串密文比较。
NewStarCTF2023公开赛week3安卓wp先看下test做了什么事,不看函数猜一下应该是做了什么编码,不然v7经过处理应该是没法直接进行明文比较了。
看了应该是改过码表的base64:
NewStarCTF2023公开赛week3安卓wp我在test函数传入时将值修改成密文的值,然后看他解密后的结果,验证下猜想:
NewStarCTF2023公开赛week3安卓wp然后继续运行,查看输出值:
NewStarCTF2023公开赛week3安卓wp把这串玩意复出来,用他的码表base64解密,发现还原后的结果正确,猜对了:
然后继续运行,查看输出值:
NewStarCTF2023公开赛week3安卓wp接下来就简单了,在test函数之前下断点,将密文解密还原,然后通过unidbg按位爆破即可。
先把密文转化成byte数组,然后跑代码。
代码如下:

  1. public boolean checkcode(String p1) throws FileNotFoundException {

  2. byte[] flagbytes = {24,64,8,16,-64,105,-39,120,32,-128,40,-47,120,8,-70,-94,-78,8,88,112,-31,40,-72,24,-70,-86,-102,-80,16,0,64,0,32,112,8,96,48,88,-78,-96,32,-39,-96,104,80,-72,-39,112,-80,-39,-104,-86,-30,-56};

  3. final boolean[] res = {false};

  4. emulator.getBackend().hook_add_new(new CodeHook() {

  5. @Override

  6. public void hook(Backend backend, long address, int size, Object user) {

  7. if (address == module.base + 0x0D3C) {

  8. RegisterContext context = emulator.getContext();

  9. byte arg0 = context.getPointerArg(0).getByte(index);

  10. byte arg1 =flagbytes[index];

  11. if (arg0 == arg1) {

  12. index++;

  13. res[0] = true;

  14. }

  15. }

  16. }

  17. @Override

  18. public void onAttach(UnHook unHook) {

  19. }

  20. @Override

  21. public void detach() {

  22. }

  23. }, module.base + 0x0D38, module.base + 0x0D48, null);

  24. String methodDec = "encode(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String";

  25. Object obj = timuclass.callStaticJniMethodObject(emulator, methodDec, p1, "deadbeef");

  26. return res[0];

  27. }

  28. public void crack() throws FileNotFoundException {

  29. String flag = "";

  30. for (int i = 0; i < 54; i++) {

  31. for (int ch = 32; ch < 127; ch++) {

  32. String str = (flag + (char) ch + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~").substring(0, 54);

  33. boolean success = checkcode(str);

  34. if (success || i + 1 == index) {

  35. flag += (char) ch;

  36. System.out.println(flag);

  37. break;

  38. }

  39. }

  40. }

  41. }

最后结果如下:

NewStarCTF2023公开赛week3安卓wp

it2hard2u

放进jadx,发现被BlackObfuscator处理过,各种分支跳转。
NewStarCTF2023公开赛week3安卓wp看了网上说JEB5.1可以去除掉这个控制流混淆,下了个新版本的(JDK17才能跑),一看确实清爽很多。
NewStarCTF2023公开赛week3安卓wp看一下流程,输入以后通过encrypt函数加密生成字符串,传给encode函数在native层,这里encrypt是个标准的rc4算法:
NewStarCTF2023公开赛week3安卓wp用IDA打开分析so,是静态注册,进来可以看到获取字符串以后,依次取出数据进行了一个32轮的运算,最后比较是否与下面的密文相等:
NewStarCTF2023公开赛week3安卓wp看算法的特征,应该是改过的tea算法,这里我选择用unidbg动态调试一下,查看运算输入的值,先还原出一部分。
unidbg架子搭好直接抠一个rc4算法过来,开始测试:
这里我下两处断点,第一处下在获取jstring的地方,第二处下在上面开始运算前取数的地方。
NewStarCTF2023公开赛week3安卓wp对应的汇编处的地址如下:
NewStarCTF2023公开赛week3安卓wp在unidbg中加两行调试:

  1. .........

  2. public Object checkcode(String p1) throws FileNotFoundException {

  3. Debugger debugger = emulator.attach();

  4. debugger.addBreakPoint(module.base+0x15AE4);

  5. debugger.addBreakPoint(module.base+0x15B28);

  6. StreamUtils rc4 = new StreamUtils();

  7. System.out.println(rc4.encryptRC4(p1, "friedchick"));

  8. String methodDec = "encode(Ljava/lang/String;)Ljava/lang/String";

  9. Object obj = timuclass.callStaticJniMethodObject(emulator, methodDec, p1, "deadbeef");

  10. return obj;

  11. }

  12. .........

开始调试,第一处断点先把传入的数据拿出来:
NewStarCTF2023公开赛week3安卓wp然后c执行,到第二处断点,我们直接看12,13两个寄存器,可以发现是4个读取,按先后,13存前一部分,12存后一部分,注意大小端序:
这里控制台输出为: x12=0xb4c3bac2 x13=0x9ac25f51
NewStarCTF2023公开赛week3安卓wp然后我们把断点打在运算完后存入数据的地方,查看值:
NewStarCTF2023公开赛week3安卓wp得到运算结果: x12=0x9c1813da x13=0xf244b822
接下来分析算法,这里的算法看起来是tea,我们照葫芦画瓢先把加密的过程模拟出来,这里稍微优化了下:

  1. #include <stdio.h>

  2. int main()

  3. {

  4. unsigned int v0 = 0x9ac25f51;

  5. unsigned int v1 = 0xb4c3bac2;

  6. int v12 = -1640531527;

  7. // 加密

  8. for (int i=0; i < 32; i++) {

  9. v0 += ((v1 >> 5) + 2) ^ ((v1 << 4) + 5) ^ (v1 + v12);

  10. v1 += ((v0 << 4) + 7) ^ (v0 + v12) ^ ((v0 >> 5) + 5);

  11. v12 -= 1640531527;

  12. }

  13. printf("%ldn",v0);

  14. printf("%ld",v1);

  15. }


运行结果如下,是正确的:

  1. 2379516734

  2. 2077360932

  3. //转16进制

  4. 0xF244B822

  5. 0x9C1813DA


此时就可以根据下面的密文用解密算法回推数据了:

  1. #include <stdio.h>

  2. int main()

  3. {

  4. unsigned int v0 = 1709447429;

  5. unsigned int v1 = 319073545;

  6. //加密 int v12 = -1640531527;

  7. int v12 = 1697034457; //解密

  8. // 加密

  9. /*

  10. for (int i=0; i < 32; i++) {

  11. v0 += ((v1 >> 5) + 2) ^ ((v1 << 4) + 5) ^ (v1 + v12);

  12. v1 += ((v0 << 4) + 7) ^ (v0 + v12) ^ ((v0 >> 5) + 5);

  13. v12 -= 1640531527;

  14. }

  15. */

  16. // 解密

  17. for (int i=0; i<32; i++) {

  18. v12 += 1640531527;

  19. v1 -= ((v0 << 4) + 7) ^ (v0 + v12) ^ ((v0 >> 5) + 5);

  20. v0 -= ((v1 >> 5) + 2) ^ ((v1 << 4) + 5) ^ (v1 + v12);

  21. }

  22. printf("%ldn",v0);

  23. printf("%ld",v1);

  24. }

最后运算得出密文:

  1. 0601c388c3acc2bdc2b8c2aec2a213c3a2c3bcc3ab0728c38f43c287c294c39d546cc295c385c3a153c2865d78c3bcc2


这里还无法直接解密,因为java层String传过来到native层通过GetStringUTFChars函数会转换成utf8,我们需要转换一下。
此时这里就碰到问题了,发现密文贴上去直接转换失败:
NewStarCTF2023公开赛week3安卓wp删除后两位发现能解出部分flag:
NewStarCTF2023公开赛week3安卓wp此时再进行测试,我将"flag{G0ddamn700h@rdf0run0w!"作为部分解,后面结尾肯定是"}",我在中间插入一个字符,通过undibg爆破,发现有大量的解正确。。。。
NewStarCTF2023公开赛week3安卓wp还是再unidbg之前的断点查看,发现只要前面是"flag{G0ddamn700h@rdf0run0w!",后面你输多少位都是可以正确,这可能是题目的bug。。。也可能是我的方法不是正确的。
可以看到后面补再多,只要"0601c388c3acc2bdc2b8c2aec2a213c3a2c3bcc3ab0728c38f43c287c294c39d546cc295c385c3a153c2865d78c3bcc2"存在了,就一定会成功。。。
NewStarCTF2023公开赛week3安卓wp最后靠手动试出来是三个感叹号。。。。


原文始发于微信公众号(gakki的童养夫):NewStarCTF2023公开赛week3安卓wp

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年10月26日02:31:52
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   NewStarCTF2023公开赛week3安卓wphttps://cn-sec.com/archives/2137071.html

发表评论

匿名网友 填写信息