write up/Hero CTF 2021
Hero CTF 2021 - JNI
heegong
2021. 5. 6. 22:42
728x90
문제
package fr.heroctf.jni;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private Button checkButton;
private EditText flagEditText;
public native boolean checkFlag(String str);
static {
System.loadLibrary("native-lib");
}
/* access modifiers changed from: protected */
@Override // androidx.activity.ComponentActivity, androidx.core.app.ComponentActivity, androidx.appcompat.app.AppCompatActivity, androidx.fragment.app.FragmentActivity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.flagEditText = (EditText) findViewById(R.id.flagEditText);
Button button = (Button) findViewById(R.id.checkButton);
this.checkButton = button;
button.setOnClickListener(new View.OnClickListener() {
/* class fr.heroctf.jni.MainActivity.AnonymousClass1 */
public void onClick(View v) {
MainActivity.this.submitFlag();
}
});
}
/* access modifiers changed from: private */
/* access modifiers changed from: public */
private void submitFlag() {
if (checkFlag(this.flagEditText.getText().toString())) {
Toast.makeText(this, "You can validate the challenge with this flag !", 0).show();
} else {
Toast.makeText(this, "Wrong flag !", 0).show();
}
}
}
jadx로 열어줬다.
private void submitFlag() {
if (checkFlag(this.flagEditText.getText().toString())) {
Toast.makeText(this, "You can validate the challenge with this flag !", 0).show();
} else {
Toast.makeText(this, "Wrong flag !", 0).show();
}
}
이 부분이 분기점이다.
checkFlag 함수를 보자.
엥? 선언이 이상하게 되어있다. 그래서 보니깐 밑에 native-lib를 불러오는 것을 알 수 있었다.
https://www.ragingrock.com/AndroidAppRE/reversing_native_libs.html
이 사이트를 참고해서
압축을 해제하고
이 폴더 중 arm-64-v8a
so파일이 있었다.
ida로 열어주고 저 함수를 hex-rays로 봤다.
bool __fastcall Java_fr_heroctf_jni_MainActivity_checkFlag(__int64 a1, __int64 a2, __int64 a3)
{
__int64 v4; // [xsp+8h] [xbp-58h]
bool v5; // [xsp+2Ch] [xbp-34h]
char v6[4]; // [xsp+54h] [xbp-Ch] BYREF
__int64 v7; // [xsp+58h] [xbp-8h]
v7 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
v4 = _JNIEnv::GetStringUTFChars(a1, a3, v6);
v5 = v6[0] == 1
&& strlen((const char *)v4) == 3LL
&& *(_BYTE *)v4 == '6'
&& *(_BYTE *)(v4 + 1) == '6'
&& *(_BYTE *)(v4 + 2) == '6';
_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2));
return v5;
}
666을 입력해야 하는 것을 볼 수 있었다.
플래그 : Hero{666}
x86_x64 파일을 보니까 쫌 더 예쁘게 보인다.