apkファイルのデコンパイルと再コンパイル

Google CTF 2018に参加するも1問も解けず。。

“shell we play a game?”がもう少しで解けそうだったけど、解けなかった。

ただ、android マルウェアに対するアプローチを学べたと思うので、メモ。

(flagを取れてないのでwrite upではない。)

問題:フラグを取得するために1,000,000回ゲームに勝ってね。添付ファイルにapk付き。

apkファイルを7zipでばらす。

ばらした中から、classes.dexをdex2jarでjarに変換。

$ ./d2j-dex2jar.sh classes.dex
dex2jar classes.dex -> ./classes-dex2jar.jar

jd-gui-windows-1.4.0に生成したjarを読ますとデコンパイルできる。
(ubuntuにjd-guiがinstallできず、windowsに切替たのは内緒)

以下は一部抜粋。progurdがかかっており、解読しにくかった。

void m()
{
Object localObject1 = N._(new Object[] { Integer.valueOf(0), N.a, Integer.valueOf(0) });
Object localObject2 = N._(new Object[] { Integer.valueOf(1), N.b, this.q, Integer.valueOf(1) });
N._(new Object[] { Integer.valueOf(0), N.c, localObject1, Integer.valueOf(2), localObject2 });
localObject1 = (byte[])N._(new Object[] { Integer.valueOf(0), N.d, localObject1, this.r });
((TextView)findViewById(2131165269)).setText(new String((byte[])localObject1));
o();
}

void n()
{
  int i = 0;
  while (i < 3)
  {
    int j = 0;
    while (j < 3)
    {
      this.l[j][i].a(a.a.a, 25);
      j += 1;
    }
    i += 1;
  }
  k();
  this.o += 1;
  Object localObject = N._(new Object[] { Integer.valueOf(2), N.e, Integer.valueOf(2) });
  N._(new Object[] { Integer.valueOf(2), N.f, localObject, this.q });
  this.q = ((byte[])N._(new Object[] { Integer.valueOf(2), N.g, localObject }));
  if (this.o == 1000000)
  {
    m();
    return;
  }
  ((TextView)findViewById(2131165269)).setText(String.format("%d / %d", new Object[] { Integer.valueOf(this.o), Integer.valueOf(1000000) }));
}

if (this.o == 1000000)をif (this.o == 1)にすれば、1度ゲームに勝つだけでフラグが生成される(ハズ)

 

apkファイルを再コンパイル可能なsmaliファイルに変換する。

$ java -jar ./apktool.jar d ./app.apk

生成されたsmaliファイルを確認。以下は一部抜粋。

.method n()V
    .locals 10

    const v9, 0xF4240

    const/4 v8, 0x1

    const/4 v7, 0x3

    const/4 v1, 0x0

    const/4 v6, 0x2

    move v2, v1

0xF4240(10進数の1000000)を0x1に変更して再コンパイル。

$ java -jar apktool_2.3.3.jar b ./app -o ./onegai.apk

apkファイルは署名が無いと、installできないため、署名を作成して、適用する。

$ keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -validity 10000
$ jarsigner -verbose -tsa http://timestamp.digicert.com -keystore ./my-release-key.keystore ./onegai.apk alias_name

最後に確認を実施する。

$ jarsigner -verify -verbose ./onegai.apk

以上で再コンパイル完了。

androidで実行してみる。

 

ゲームをクリアした後に表示されるであろう、flagが文字化けしている・・

この後smaliをいじるもflagはでなかった。。