-
-
[原创]bugku CTF安卓逆向LoopAndLoop(阿里CTF)
-
发表于: 2024-2-9 23:49 13544
-
来自bugku的LoopAndLoop(阿里CTF)。
拿到压缩包解压,看到文件时APK格式,直接拖到夜神模拟器看看。
简单的测试了下如下
将APK拖到JADX,找到MainActivity,代码如下
安卓层面主要的逻辑
以上代码逻辑
双击check函数,一层层引用可以找到最终调用的是
JADX保存文件到本地,直接将so文件拖入32位IDA7.5版本,其支持arm F5的版本也行。
查看Exports 页面,下面时部分导出函数
双击函数Java_net_bluelotus_tomorrow_easyandroid_MainActivity_chec,直接跳转到汇编代码页面,F5就可得到逻辑代码。简单的修改了下第一个参数的数据类型,代码逻辑看着更清晰了
可以看到so文件的代码又去调用了UI层的逻辑。
结合MainActivity中的代码和so中的代码,整理chec函数逻辑如下
既然是个int值,从0开始穷举就可以了。但是这绝对不是唯一办法。
先看看前0-99的输出吧!
结果
可以看出是结果是线性的。首先我们会想到2分法。
2分法计算如下
通过仔细观察也可以看出i增长1,计算结果也增长1。这样可以直接算出想要的i值。
计算结果。
找到so中函数stringFromJNI2,方法同上
剔除无用参数得到c语言逻辑
最后得到flag如下
public
class
MainActivity
extends
AppCompatActivity {
public
native
int
chec(
int
i,
int
i2);
public
native
String stringFromJNI2(
int
i);
/* JADX INFO: Access modifiers changed from: protected */
@Override
// android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut, android.app.Activity
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
final
TextView tv1 = (TextView) findViewById(R.id.textView2);
final
TextView tv2 = (TextView) findViewById(R.id.textView3);
final
EditText ed = (EditText) findViewById(R.id.editText);
button.setOnClickListener(
new
View.OnClickListener() {
// from class: net.bluelotus.tomorrow.easyandroid.MainActivity.1
@Override
// android.view.View.OnClickListener
public
void
onClick(View v) {
String in_str = ed.getText().toString();
try
{
int
in_int = Integer.parseInt(in_str);
if
(MainActivity.
this
.check(in_int,
99
) ==
1835996258
) {
tv1.setText(
"The flag is:"
);
tv2.setText(
"alictf{"
+ MainActivity.
this
.stringFromJNI2(in_int) +
"}"
);
return
;
}
tv1.setText(
"Not Right!"
);
}
catch
(NumberFormatException e) {
tv1.setText(
"Not a Valid Integer number"
);
}
}
});
}
@Override
// android.app.Activity
public
boolean
onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return
true
;
}
@Override
// android.app.Activity
public
boolean
onOptionsItemSelected(MenuItem item) {
int
id = item.getItemId();
if
(id == R.id.action_settings) {
return
true
;
}
return
super
.onOptionsItemSelected(item);
}
public
String messageMe(String text) {
return
"LoopOk"
+ text;
}
public
int
check(
int
input,
int
s) {
return
chec(input, s);
}
public
int
check1(
int
input,
int
s) {
int
t = input;
for
(
int
i =
1
; i <
100
; i++) {
t += i;
}
return
chec(t, s);
}
public
int
check2(
int
input,
int
s) {
int
t = input;
if
(s %
2
==
0
) {
for
(
int
i =
1
; i <
1000
; i++) {
t += i;
}
return
chec(t, s);
}
for
(
int
i2 =
1
; i2 <
1000
; i2++) {
t -= i2;
}
return
chec(t, s);
}
public
int
check3(
int
input,
int
s) {
int
t = input;
for
(
int
i =
1
; i <
10000
; i++) {
t += i;
}
return
chec(t, s);
}
static
{
System.loadLibrary(
"lhm"
);
}
}
public
class
MainActivity
extends
AppCompatActivity {
public
native
int
chec(
int
i,
int
i2);
public
native
String stringFromJNI2(
int
i);
/* JADX INFO: Access modifiers changed from: protected */
@Override
// android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut, android.app.Activity
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
final
TextView tv1 = (TextView) findViewById(R.id.textView2);
final
TextView tv2 = (TextView) findViewById(R.id.textView3);
final
EditText ed = (EditText) findViewById(R.id.editText);
button.setOnClickListener(
new
View.OnClickListener() {
// from class: net.bluelotus.tomorrow.easyandroid.MainActivity.1
@Override
// android.view.View.OnClickListener
public
void
onClick(View v) {
String in_str = ed.getText().toString();
try
{
int
in_int = Integer.parseInt(in_str);
if
(MainActivity.
this
.check(in_int,
99
) ==
1835996258
) {
tv1.setText(
"The flag is:"
);
tv2.setText(
"alictf{"
+ MainActivity.
this
.stringFromJNI2(in_int) +
"}"
);
return
;
}
tv1.setText(
"Not Right!"
);
}
catch
(NumberFormatException e) {
tv1.setText(
"Not a Valid Integer number"
);
}
}
});
}
@Override
// android.app.Activity
public
boolean
onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return
true
;
}
@Override
// android.app.Activity
public
boolean
onOptionsItemSelected(MenuItem item) {
int
id = item.getItemId();
if
(id == R.id.action_settings) {
return
true
;
}
return
super
.onOptionsItemSelected(item);
}
public
String messageMe(String text) {
return
"LoopOk"
+ text;
}
public
int
check(
int
input,
int
s) {
return
chec(input, s);
}
public
int
check1(
int
input,
int
s) {
int
t = input;
for
(
int
i =
1
; i <
100
; i++) {
t += i;
}
return
chec(t, s);
}
public
int
check2(
int
input,
int
s) {
int
t = input;
if
(s %
2
==
0
) {
for
(
int
i =
1
; i <
1000
; i++) {
t += i;
}
return
chec(t, s);
}
for
(
int
i2 =
1
; i2 <
1000
; i2++) {
t -= i2;
}
return
chec(t, s);
}
public
int
check3(
int
input,
int
s) {
int
t = input;
for
(
int
i =
1
; i <
10000
; i++) {
t += i;
}
return
chec(t, s);
}
static
{
System.loadLibrary(
"lhm"
);
}
}
int
in_int = Integer.parseInt(in_str);
if
(MainActivity.
this
.check(in_int,
99
) ==
1835996258
) {
tv1.setText(
"The flag is:"
);
tv2.setText(
"alictf{"
+ MainActivity.
this
.stringFromJNI2(in_int) +
"}"
);
return
;
}
tv1.setText(
"Not Right!"
);
int
in_int = Integer.parseInt(in_str);
if
(MainActivity.
this
.check(in_int,
99
) ==
1835996258
) {
tv1.setText(
"The flag is:"
);
tv2.setText(
"alictf{"
+ MainActivity.
this
.stringFromJNI2(in_int) +
"}"
);
return
;
}
tv1.setText(
"Not Right!"
);
public native
int
chec(
int
i,
int
i2);
public native
int
chec(
int
i,
int
i2);
Name Address Ordinal
Java_net_bluelotus_tomorrow_easyandroid_MainActivity_chec
00000E8C
Java_net_bluelotus_tomorrow_easyandroid_MainActivity_stringFromJNI2
00000F18
....
Name Address Ordinal
Java_net_bluelotus_tomorrow_easyandroid_MainActivity_chec
00000E8C
Java_net_bluelotus_tomorrow_easyandroid_MainActivity_stringFromJNI2
00000F18
....
int
__fastcall Java_net_bluelotus_tomorrow_easyandroid_MainActivity_chec(JNIEnv *jenv,
int
a2,
int
t,
int
s)
{
jclass v5;
// r7
int
result;
// r0
int
v10[9];
// [sp+1Ch] [bp-24h] BYREF
v5 = (*jenv)->FindClass(jenv,
"net/bluelotus/tomorrow/easyandroid/MainActivity"
);
v10[0] = _JNIEnv::GetMethodID(jenv, v5,
"check1"
,
"(II)I"
);
v10[1] = _JNIEnv::GetMethodID(jenv, v5,
"check2"
,
"(II)I"
);
v10[2] = _JNIEnv::GetMethodID(jenv, v5,
"check3"
,
"(II)I"
);
if
( s - 1 <= 0 )
result = t;
else
result = _JNIEnv::CallIntMethod(jenv, a2, v10[2 * s % 3], t, s - 1);
//
// 99 * 2 % 3 = 0
// 98 * 2 % 3 = 1
// 97 * 2 % 3 = 2
// 96 * 2 % 3 = 0
return
result;
}
int
__fastcall Java_net_bluelotus_tomorrow_easyandroid_MainActivity_chec(JNIEnv *jenv,
int
a2,
int
t,
int
s)
{
jclass v5;
// r7
int
result;
// r0
int
v10[9];
// [sp+1Ch] [bp-24h] BYREF
v5 = (*jenv)->FindClass(jenv,
"net/bluelotus/tomorrow/easyandroid/MainActivity"
);
v10[0] = _JNIEnv::GetMethodID(jenv, v5,
"check1"
,
"(II)I"
);
v10[1] = _JNIEnv::GetMethodID(jenv, v5,
"check2"
,
"(II)I"
);
v10[2] = _JNIEnv::GetMethodID(jenv, v5,
"check3"
,
"(II)I"
);
if
( s - 1 <= 0 )
result = t;
else
result = _JNIEnv::CallIntMethod(jenv, a2, v10[2 * s % 3], t, s - 1);
//
// 99 * 2 % 3 = 0
// 98 * 2 % 3 = 1
// 97 * 2 % 3 = 2
// 96 * 2 % 3 = 0
return
result;
}
int
chec(
int
t,
int
s);
int
check1(
int
input
,
int
s)
{
int
t
=
input
;
for
(
int
i
=
1
; i <
100
; i
+
+
)
{
t
+
=
i;
}
return
chec(t, s);
}
int
check2(
int
input
,
int
s)
{
int
t
=
input
;
if
(s
%
2
=
=
0
)
{
for
(
int
i
=
1
; i <
1000
; i
+
+
)
{
t
+
=
i;
}
return
chec(t, s);
}
for
(
int
i2
=
1
; i2 <
1000
; i2
+
+
)
{
t
-
=
i2;
}
return
chec(t, s);
}
int
check3(
int
input
,
int
s)
{
int
t
=
input
;
for
(
int
i
=
1
; i <
10000
; i
+
+
)
{
t
+
=
i;
}
return
chec(t, s);
}
typedef
int
(
*
pfn_check)(
int
,
int
);
pfn_check check_fns[
3
]
=
{
check1, check2, check3};
int
chec(
int
t,
int
s)
{
if
(s
-
1
<
=
0
)
{
/
*
code
*
/
return
t;
}
else
{
return
check_fns[
2
*
s
%
3
](t, s
-
1
);
}
}
int
chec(
int
t,
int
s);
int
check1(
int
input
,
int
s)
{
int
t
=
input
;
for
(
int
i
=
1
; i <
100
; i
+
+
)
{
t
+
=
i;
}
return
chec(t, s);
}
int
check2(
int
input
,
int
s)
{
int
t
=
input
;
if
(s
%
2
=
=
0
)
{
for
(
int
i
=
1
; i <
1000
; i
+
+
)
{
t
+
=
i;
}
return
chec(t, s);
}
for
(
int
i2
=
1
; i2 <
1000
; i2
+
+
)
{
t
-
=
i2;
}
return
chec(t, s);
}
int
check3(
int
input
,
int
s)
{
int
t
=
input
;
for
(
int
i
=
1
; i <
10000
; i
+
+
)
{
t
+
=
i;
}
return
chec(t, s);
赞赏记录
参与人
雪币
留言
时间
一笑人间万事
为你点赞~
2024-5-30 01:00
zxk1ng
为你点赞~
2024-5-2 11:44
sky东
为你点赞~
2024-3-15 13:34
slcn
为你点赞~
2024-2-17 07:53
赞赏
他的文章
看原图
赞赏
雪币:
留言: