前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >【愚公系列】2023年04月 攻防世界-MOBILE(Android2.0)

【愚公系列】2023年04月 攻防世界-MOBILE(Android2.0)

作者头像
愚公搬代码
发布2023-04-21 19:28:24
发布2023-04-21 19:28:24
44300
代码可运行
举报
文章被收录于专栏:历史专栏历史专栏
运行总次数:0
代码可运行


前言

下面介绍两个反编译工具

  • jadx是一个用于反编译Android APK文件的开源工具,静态反编译,查找索引功能强大
  • jeb和IDA很像,属于动态调试,可以看java汇编也可以生成伪代码,还可以动态attach到目标调试

对于so文件的逆向工具选择

  • IDA逆向工具是一款反汇编器,被广泛应用于软件逆向工程领域,能够反汇编各种不同平台的二进制程序代码,并还原成可读的汇编代码。

一、Android2.0

1.题目

2.答题

1、将apk拖进jadx工具反编译,可以看到调用这个函数JNI.getResult,返回值为0就提示wrong。

2、因为getResult是JNI函数,所以需要看一看so文件,找到这个函数,反汇编代码如下:

选择函数窗体搜索getResult

点击后,在出现的汇编代码中,按F5就可以查看反编译的代码了~

代码语言:javascript
代码运行次数:0
复制
bool __fastcall Java_com_example_test_ctf03_JNI_getResult(int a1, int a2, int a3)
{
  _BOOL4 v3; // r4
  const char *v4; // r8
  char *v5; // r6
  char *v6; // r4
  char *v7; // r5
  int i; // r0
  int j; // r0

  v3 = 0;
  v4 = (const char *)(*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)a1 + 676))(a1, a3, 0);
  if ( strlen(v4) == 15 )
  {
    v5 = (char *)malloc(1u);
    v6 = (char *)malloc(1u);
    v7 = (char *)malloc(1u);
    Init(v5, v6, v7, v4, 15);
    if ( !First(v5) )
      goto LABEL_6;
    for ( i = 0; i != 4; ++i )
      v6[i] ^= v5[i];
    if ( !strcmp(v6, a5) )
    {
      for ( j = 0; j != 4; ++j )
        v7[j] ^= v6[j];
      v3 = strcmp(v7, "AFBo}") == 0;
    }
    else
    {
LABEL_6:
      v3 = 0;
    }
  }
  return v3;
}

改一下函数的形参类型:JNIEnv *env, jobject obj, jstring str,再看看伪代码:

代码语言:javascript
代码运行次数:0
复制
bool __fastcall Java_com_example_test_ctf03_JNI_getResult(JNIEnv *a1, jobject a2, jstring a3)
{
  int v3; // r4
  const char *v4; // r8
  char *v5; // r6
  char *v6; // r4
  char *v7; // r5
  int i; // r0
  int j; // r0

  v3 = 0;
  v4 = (*a1)->GetStringUTFChars(a1, a3, 0);
  if ( strlen(v4) == 15 )
  {
    v5 = (char *)malloc(1u);
    v6 = (char *)malloc(1u);
    v7 = (char *)malloc(1u);
    Init(v5, v6, v7, v4, 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;
}

先看GetStringUTFChars将我们输入的java类型的str变成c语言形式的字符串,然后判断长度是否等于15,否则返回0,接着v5,v6,v7分配了一个字符的大小,执行Init函数,进去看一看这个函数是干啥的:

代码语言:javascript
代码运行次数:0
复制
int __fastcall Init(int result, char *a2, char *a3, const char *a4, int a5)
{
  int v5; // r5
  int v6; // r10
  int v7; // r6

  if ( a5 < 1 )
  {
    v6 = 0;
  }
  else
  {
    v5 = 0;
    v6 = 0;
    do
    {
      v7 = v5 % 3;
      if ( v5 % 3 == 2 )
      {
        a3[v5 / 3u] = a4[v5];
      }
      else if ( v7 == 1 )
      {
        a2[v5 / 3u] = a4[v5];
      }
      else if ( !v7 )
      {
        ++v6;
        *(_BYTE *)(result + v5 / 3u) = a4[v5];
      }
      ++v5;
    }
    while ( a5 != v5 );
  }
  *(_BYTE *)(result + v6) = 0;
  a2[v6] = 0;
  a3[v6] = 0;
  return result;
}

代入去想(注意这里要把result看成*a1),15位字符串,do while循环15次,模3赋值a1,a2,a3,也就是将我输入的字符串按如下方式处理:

代码语言:javascript
代码运行次数:0
复制
a1就是str[0],str[3],str[6],str[9],str[12]
a2就是str[1],str[4],str[7],str[10],str[13]
a3就是str[2],str[5],str[8],str[11],str[14]

也就是对应getResult函数中的v5,v6,v7

3、分析v5,v6,v7的来源

接着看第一个if ( !First(v5) ),这里是将v5进行了4次循环处理,将自身乘以2然后异或0x80,v5通过前面的分析,可以知道一共有5位,这里只对前4位进行了处理,处理后的v5必须等于"LN^dl"。

代码语言:javascript
代码运行次数:0
复制
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;
}

再回来,又看到一个4次的for循环,这一次处理的是v6,将自身与v5的每一位进行异或,那串字符串反编译有点问题,看data进行比较。

代码语言:javascript
代码运行次数:0
复制
    for ( i = 0; i != 4; ++i )
      v6[i] ^= v5[i];
    if ( !strcmp(v6, " 5-\x16a") )

        .rodata:00002888 unk_2888        DCB 0x20                ; DATA XREF: Second(char *,char *)+18↑o
        .rodata:00002888                                         ; Second(char *,char *)+1C↑o ...
        .rodata:00002889                 DCB 0x35 ; 5
        .rodata:0000288A                 DCB 0x2D ; -
        .rodata:0000288B                 DCB 0x16
        .rodata:0000288C                 DCB 0x61 ; a
        .rodata:0000288D                 DCB    0

最后又是一组循环,v7的处理和v6一样,也是将自身与v6异或,同样只处理前4位,然后和"AFBo}"比较。

代码语言:javascript
代码运行次数:0
复制
 for ( j = 0; j != 4; ++j )
        v7[j] ^= v6[j];
      v3 = strcmp(v7, "AFBo}") == 0;

4、逆向还原v5、v6、v7

代码语言:javascript
代码运行次数:0
复制
#include <stdio.h>

void getV5(char *v5)
{
    int i;
    char str[6] = "LN^dl";
    ;
    for (i = 0; i < 4; i++)
    {
        v5[i] = (str[i] ^ 0x80) / 2;
    }
    v5[i] = str[i];
    v5[i + 1] = 0;
}

void getV6(char *v6)
{
    int i;
    char str[6] = "LN^dl";
    char str2[6] = {0x20, 0x35, 0x2d, 0x16, 0x61, 0};

    for (i = 0; i < 4; i++)
    {
        v6[i] = str2[i] ^ str[i];
    }
    v6[i] = str2[i];
    v6[i + 1] = 0;
}

void getV7(char *v7)
{
    int i;
    char str2[6] = {0x20, 0x35, 0x2d, 0x16, 0x61, 0};
    char str3[6] = "AFBo}";

    for (i = 0; i < 4; i++)
    {
        v7[i] = str3[i] ^ str2[i];
    }
    v7[i] = str3[i];
    v7[i + 1] = 0;
}

int main()
{
    char v5[6];
    char v6[6];
    char v7[6];
    char flag[15];

    getV5(v5);
    getV6(v6);
    getV7(v7);

    int j= 0;
    for (int i = 0; i < 5; i++)
    {
        flag[j] = v5[i];
        flag[j+1] = v6[i];
        flag[j+2] = v7[i];

        j=j+3;
    }

    printf("%s", flag);

    return 1;
}

优化下代码

代码语言:javascript
代码运行次数:0
复制
#include <stdio.h>

int main()
{
    char str[6] = "LN^dl";
    char str2[6] = {0x20, 0x35, 0x2d, 0x16, 0x61, 0};
    char str3[6] = "AFBo}";
    char flag[15];

    int i = 0;
    int j = 0;
    for (i = 0; i < 4; i++)
    {
        flag[j] = (str[i] ^ 0x80) / 2;
        flag[j + 1] = str2[i] ^ str[i];
        flag[j + 2] = str3[i] ^ str2[i];

        j = j + 3;
    }

    flag[j] = str[i];
    flag[j + 1] =str2[i];
    flag[j + 2] = str3[i];
        flag[j + 3] = '\0'; 

    printf("%s", flag);

    return 1;
}

python脚本如下:

代码语言:javascript
代码运行次数:0
复制
a1 = ""
a2 = ""
a3 = ""

key1 = "LN^dl"
for i in range(4):
    a1 += chr((ord(key1[i]) ^ 0x80) // 2)
a1 += key1[4]

key2 = " 5-\x16a"
for i in range(4):
    a2 += chr(ord(key2[i]) ^ ord(key1[i]))
a2 += key2[4]

key3 = "AFBo}"
for i in range(4):
    a3 += chr(ord(key3[i]) ^ ord(key2[i]))
a3 += key3[4]

flag = ""
for i in range(5):
    flag = flag + a1[i] + a2[i] + a3[i]

print(flag)
代码语言:javascript
代码运行次数:0
复制
flag{sosorryla}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-04-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一、Android2.0
    • 1.题目
    • 2.答题
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档