关于攻防世界ph0en1x ctf的逆向

1、打开画面内容如下,需要进行flag验证

2、那么肯定有个验证函数进行判断,直接跟进对应的活动进行反编译查看比较函数,这里对应的活动是MainActivity,可以直接看到判断函数

  public void onGoClick(View paramView)
  {
    paramView = this.etFlag.getText().toString();
    if (getSecret(getFlag()).equals(getSecret(encrypt(paramView)))) {
      Toast.makeText(this, "Success", 1).show();
    }
    for (;;)
    {
      return;
      Toast.makeText(this, "Failed", 1).show();
    }
  }

3、关键看if判断语句,它是通过getSecret(getFlag()) 和 getSecret(encrypt(你输入的值)) 进行比较,如果相同则成功,那么也就是让getFlag和encrypt(你输入的值)相同就行,那么可以先进行调试getFlag返回值是什么,结果发现两个都是native方法,都是写在so层的,那么也就是需要进入so层进行调试

  public native String encrypt(String paramString);
  
  public native String getFlag();
  
  public String getSecret(String paramString)

4、这里自己讲java层和so层的调试,顺便复习下这几天学的知识,这里调试用的是JEB,直接在函数开头进行断点,执行如下命令,然后进行JEB断点调试

adb shell am start -D -n com.ph0en1x.android_crackme/com.ph0en1x.android_crackme.MainActivity

5、总的过程就是先 CH - 14H就是获取输入框中的字符串,接着16H - 24H 获取getSecret(getFalg())的内容后面就是获取加密输入框中的字符串,最后进行比较

那么这里就可以拿到getFalg的内容是多少,1CH的时候放到v1寄存器中

值为:ekXfXXXXXXfn0mFXXXXXXrbXqanqntfgXXXXX

那么现在就是如何让 this.encrypt("输入的值") == ekXfXXXXXXfn0mFXXXXXXrbXqanqntfgXXXXX 这个条件进行成立,可以继续调试看下v2寄存器中处理的值(也就是encrypt函数处理过后),可以发现只是转换为ascii码然后进行-1再还原的操作

那么也就是让v1的寄存器全部都+1就可以进行直接相等了,还原代码如下

char s[]="ek`fz@q2^x/t^fn0mF^6/^rb`qanqntfg^E`hq|";
int main()
{
    for(int i=0;i<strlen(s);i++)
    {
        printf("%c",s[i]+1);
    }
    return 0;
}

答案就是: flag{Ar3_y0u_go1nG_70_scarborough_Fair}

接着继续进so层调试,看看getFlag函数是如何实现的,直接将so文件拖入ida分析,为什么是这个文件,因为静态代码块中加载动态链接库的时候就是这个

getFlag函数如下,就是开辟了一段栈空间,然后进行赋值操作

继续看encrypt

上面也就是实现了自增1,encrypt的作用!

posted @ 2020-09-20 03:06  zpchcbd  阅读(497)  评论(0编辑  收藏  举报