Hack The Box mobile 문제인 Waiting 문제를 풀어봅시다.
요즘 모바일을 도통 안해서 다까먹어서… 큰일
개요
제일 먼저 Waiting 앱 실행 시 아래와 같습니다. 그리고 바로 앱이 종료됩니다.
이 앱은 모든 종류의 사용자를 위한 토큰 또는 비밀을 생성하는 데 유용합니다. 업데이트: 다른 앱의 요청 토큰에 대한 일부 베타 기능이 테스트 중입니다. 또한 앱의 리팩토링으로 인해 다른 권한 기능이 삭제되었습니다.
Manifest.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<manifest android:compileSdkVersion="31" android:compileSdkVersionCodename="12" android:versionCode="1" android:versionName="1.0" package="com.example.waiting" platformBuildVersionCode="31" platformBuildVersionName="12" xmlns:android="http://schemas.android.com/apk/res/android">
<uses-sdk android:minSdkVersion="22" android:targetSdkVersion="31"/>
<application android:allowBackup="true" android:appComponentFactory="android.support.v4.app.CoreComponentFactory" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.HTBChallenge1">
<activity android:exported="true" android:launchMode="1" android:name="com.example.waiting.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:exported="false" android:launchMode="1" android:name="com.example.waiting.MenuActivity">
<intent-filter>
<action android:name="com.example.waiting.MENU_ACTION"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity android:exported="false" android:name="com.example.waiting.SecretActivity"/>
</application>
</manifest>
Solve
먼저 문제를 풀었던 호피가 알려주는 대로 문제를 안봐도 풀린다고 하여 풀었습니다.
아래는 플래그를 찾을 수 있는 핵심 코드입니다. Native 함수인 getdxXEPMNe
으로 getPackageName
을 전송합니다. getPackageName
= com.example.waiting
이 됩니다. 해당 함수 결과로 setText
로 보여주는데 해당 값이 Flag가 됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
protected void onCreate(Bundle bundle0) {
super.onCreate(bundle0);
this.setContentView(0x7F09001E); // layout:activity_secret
TextView textView0 = (TextView)this.findViewById(0x7F0700D5); // id:text_secret_message
try {
do {
label_7:
a.a(this);
if(this.getReferrer().toString().endsWith(this.getPackageName())) {
String s = new Secrets().getdxXEPMNe(this.getPackageName());
while(true) {
textView0.setText(s);
if((SecretActivity.j + 102) * (SecretActivity.j + 102) * 7 - 1 - SecretActivity.j != 0) {
break;
}
}
}
ida로 열어본 getdxXEPMNe
함수입니다. 입력받은 패키지명을 sha256
을 합니다. 그 뒤 v10[i - i / v7 * v7] ^ v6;
으로 xor을 하게 되는데 여기서 막혔습니다. 파이썬으로 돌리니 계속 0이 출력되었기 때문입니다. 호피에 의하면 C로 하면 0.0, 0.9, 1.9 …으로 변환된다고 합니다.
그렇다면 곧 byte_13B5[i] ^ sha256[i]
값이 Flag가 됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
jstring __fastcall Java_com_example_waiting_Secrets_getdxXEPMNe(JNIEnv *a1, __int64 a2, __int64 a3)
{
const char *v4; // x0
unsigned __int64 i; // x23
char v6; // w26
unsigned __int64 v7; // x0
_BYTE v9[52]; // [xsp+0h] [xbp-C0h] BYREF
char v10[68]; // [xsp+34h] [xbp-8Ch] BYREF
__int64 v11; // [xsp+78h] [xbp-48h]
v11 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 0xD, 0, 2)) + 0x28);
v4 = (*a1)->GetStringUTFChars(a1, a3, 0LL); // com.example.waiting
sha256(v4, v10);
for ( i = 0LL; i != 48; ++i )
{
v6 = byte_13B5[i];
v7 = __strlen_chk(v10, 65u);
v9[i] = v10[i - i / v7 * v7] ^ v6;
}
v9[48] = 0;
return (*a1)->NewStringUTF(a1, v9);
xor을 하니 FLAG가 잘나옵니다. 처음에는 binascii에 unhexlify 하여 할려고 했는데 2바이트씩 바이너리값으로 바뀌어서 오류가 많았습니다. 알고보니 굳이 unhexlify를 하지 않고 Flag가 단순 문자열이기 때문에 ord로 풀릴 수 있다는 걸 알게되었습니다.
ord, bin등 타입에 대한 공부가 부족함을 많이 느끼는 문제였습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
byte_13B5 = [0x71, 0x67, 0x23, 0x4A, 0x23, 0x08, 0x01, 0x01, 0x67, 0x05, 0x41, 0x41, 0x03, 0x5B, 0x51, 0x3A, 0x51, 0x5E, 0x17, 0x5C,0x6A, 0x4D, 0x52, 0x09, 0x48, 0x57, 0x14, 0x05, 0x5A, 0x5F,0x6A, 0x05, 0x0C, 0x06, 0x05, 0x0D, 0x50, 0x69, 0x05, 0x54, 0x55,0x58, 0x51, 0x07, 0x0E, 0x4B, 0x10, 0x18 ]
sha256 = [0x39, 0x33, 0x61, 0x31, 0x65, 0x64, 0x35, 0x66, 0x38, 0x30, 0x35, 0x33, 0x33, 0x35, 0x36, 0x65, 0x65, 0x30, 0x63, 0x35, 0x35, 0x39, 0x66, 0x64, 0x38, 0x32, 0x66, 0x34, 0x34, 0x38, 0x35, 0x66, 0x64, 0x35, 0x66, 0x66, 0x65, 0x36, 0x63, 0x64, 0x65, 0x34, 0x34, 0x63, 0x62, 0x38, 0x31, 0x65, 0x37, 0x33, 0x61, 0x38, 0x65, 0x33, 0x33, 0x38, 0x34, 0x35, 0x34, 0x65, 0x30, 0x38, 0x62, 0x38]
sha256_packageName = "93a1ed5f8053356ee0c559fd82f4485fd5ffe6cde44cb81e73a8e338454e08b8"
flag = ''
for i in range(0,48):
v9 = byte_13B5[i] ^ ord(sha256_packageName[i])
flag += chr(v9)
print(flag)
후기
문제를 풀면서 느낀점은 연산을 할때 언어 C, python의 결과가 다를수도 있다는 점과 타입에 대한 부족함을 많이 느끼게 되는 시간이였습니다.
첨에 앱이 계속 안켜져서 매지스크쪽 만지다가 벽돌이 되어 순정 펌웨어로 밀고 Magisk로 펌웨어를 업데이트하여 루팅를 했는데 글로 남기면 좋을듯