新手题用了三天才误打误撞完成了,惭愧惭愧
接下来进入正题
第一步先查壳
没有壳,先跑起来看一下,可以看到有长度检测
拖入OD,搜索字符串,发现tips和错误提示
Tips:same like last year question
好家伙,那不就是2023HappyNewYear52PoJie呗,然而并不是
双击Length Error
004012D7 . C70424 000044>mov dword ptr ss:[esp],【2023春.00440000 ; |【2023春节】解题领红包之贰
004012F4 . B8 1B004400 mov eax,【2023春.0044001B ; Please input password:
004012F9 . 894424 04 mov dword ptr ss:[esp+0x4],eax
004012FD . C70424 D03344>mov dword ptr ss:[esp],【2023春.004433D0
00401304 . C745 98 05000>mov dword ptr ss:[ebp-0x68],0x5
0040130B . E8 E0B00300 call 【2023春.0043C3F0
00401310 . 890424 mov dword ptr ss:[esp],eax
00401313 . E8 A89E0300 call 【2023春.0043B1C0
00401318 . C70424 703444>mov dword ptr ss:[esp],【2023春.00443470 ; |D
0040131F . 8D5D D8 lea ebx,dword ptr ss:[ebp-0x28]
00401322 . 895C24 04 mov dword ptr ss:[esp+0x4],ebx
00401326 . E8 45C40300 call 【2023春.0043D770
0040132B . 8B75 D8 mov esi,dword ptr ss:[ebp-0x28]
0040132E 837E F4 1D cmp dword ptr ds:[esi-0xC],0x1D
00401332 . 0F84 A5000000 je 【2023春.004013DD
00401338 . C70424 D03344>mov dword ptr ss:[esp],【2023春.004433D0
0040133F . BF 34004400 mov edi,【2023春.00440034 ; Length Error, please try again
可以看到上面有一个比较cmp dword ptr ds:[esi-0xC],0x1D
虽然看不懂,但是看了大佬去年的解题过程,得知这应该是判断长度的。0x1D转为10进制是29,经过验证,flag长度确实是29
接下来,便没有了思路,去年的题目flag直接出现在寄存器中。我照着教程https://www.52pojie.cn/forum.php?mod=viewthread&tid=1588529怎么也找不到
试过IDA,伪代码硬是看不懂,不过我发现第三个call就只有一处调用,就跟进去看了一下
下断点,跑起来然后单步进入
返回后,发现有个跳转会跳到失败,看到过教程里说可以修改Z 标志位不让它跳转,继续单步往下走
又一个jnz,不让它跳,渐渐发现这是一个循环,大概是取出每一个字符进行比较,后来想到是flag开头,结合Tipsflag{2023HappyNewYear52PoJie} 结果还不对,没办法多走几步,发现52PoJie在前面flag{52PoJie2023HappyNewYear}
没学过逆向,把题解出来成就感还是不错的: )
二、Android 初级题一
安装好,打开看一下,有一个按钮,点击999次就能获得flag
这就打开连点器 (
按一下按钮就会发出鸡叫
用MT提取apk,没有加固
接着xml搜索 点击,复制id,在dex中搜索
进入MainActivity,转成java,关键在于check函数
public static final void onCreate$lambda-0(MainActivity mainActivity, TextView textView, View view) {
Intrinsics.checkNotNullParameter(mainActivity, "this$0");
Intrinsics.checkNotNullParameter(textView, "$key");
Context context = (Context) mainActivity;
mainActivity.jntm(context);
textView.setText(String.valueOf(mainActivity.num));
if (mainActivity.check() == 999) {
Toast.makeText(context, "快去论坛领CB吧!", 1).show();
textView.setText(mainActivity.decrypt("hnci}|jwfclkczkppkcpmwckng\u007f", 2));
}
}
直接返回999
[
点击一下,成功得到flag
三、Android 初级题二
要求输入UID和flag
如上搜索验证后,判断发生在MainActivity
用Jadx打开,定位到MainActivity,有一个关于按钮的校验,在动态调试时,按钮会不可见
public void onStart() {
super.onStart();
if (b()) {
return;
}
Button button = this.btn_check;
if (button == null) {
Intrinsics.throwUninitializedPropertyAccessException("btn_check");
button = null;
}
button.setVisibility(8);
}
private final boolean b() {
String str;
Signature[] signatureArr;
try {
if (Build.VERSION.SDK_INT >= 28) {
signatureArr = getPackageManager().getPackageInfo(getPackageName(), 134217728).signingInfo.getApkContentsSigners();
} else {
signatureArr = getPackageManager().getPackageInfo(getPackageName(), 64).signatures;
}
str = MD5Utils.INSTANCE.MD5(Base64Utils.INSTANCE.encodeToString(signatureArr[0].toByteArray()));
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
str = "";
}
return Intrinsics.areEqual("12178c3f7f6b734a8a3d0ace3092bd32", str);
}
判断flag是否正确,判断逻辑在a.B
public static final void m25onCreate$lambda0(MainActivity this$0, View view) {
Intrinsics.checkNotNullParameter(this$0, "this$0");
A a = A.INSTANCE;
EditText editText = this$0.edit_uid;
EditText editText2 = null;
if (editText == null) {
Intrinsics.throwUninitializedPropertyAccessException("edit_uid");
editText = null;
}
String obj = StringsKt.trim((CharSequence) editText.getText().toString()).toString();
EditText editText3 = this$0.edit_flag;
if (editText3 == null) {
Intrinsics.throwUninitializedPropertyAccessException("edit_flag");
} else {
editText2 = editText3;
}
if (a.B(obj, StringsKt.trim((CharSequence) editText2.getText().toString()).toString())) {
Toast.makeText(this$0, "恭喜你,flag正确!", 1).show();
} else {
Toast.makeText(this$0, "flag错误哦,再想想!", 1).show();
}
}
定位到B方法,可以看出是flag{}的形式
// str:UID str:flag
public final boolean B(String str, String str2) {
Intrinsics.checkNotNullParameter(str, "str");
Intrinsics.checkNotNullParameter(str2, "str2");
if (!(str.length() == 0 && str2.length() == 0) && StringsKt.startsWith$default(str2, "flag{", false, 2, (Object) null) && StringsKt.endsWith$default(str2, "}", false, 2, (Object) null)) {
String substring = str2.substring(5, str2.length() - 1);
Intrinsics.checkNotNullExpressionValue(substring, "this as java.lang.String…ing(startIndex, endIndex)");
C c = C.INSTANCE;
MD5Utils mD5Utils = MD5Utils.INSTANCE;
Base64Utils base64Utils = Base64Utils.INSTANCE;
String encode = B.encode(str + "Wuaipojie2023");
Intrinsics.checkNotNullExpressionValue(encode, "encode(str3)");
byte[] bytes = encode.getBytes(Charsets.UTF_8);
Intrinsics.checkNotNullExpressionValue(bytes, "this as java.lang.String).getBytes(charset)");
return Intrinsics.areEqual(substring, c.cipher(mD5Utils.MD5(base64Utils.encodeToString(bytes)), 5));
}
return false;
}
太多了,不想看,直接上jeb动态调试,具体看正己哥哥的教程
[吾爱破解安卓逆向入门教程《安卓逆向这档事》
给b方法赋值,防止按扭消失
找到B方法,下断
输入UID和flag,验证。成功断下,查看变量,发现flag
96382gjk7f53h2f97jifi1hfhgg9ggjk以flag{}包裹
flag正确
web初级题
虽然没解出来,记录一下不知道对不对
flag6
第一个是flag6,通过拨号音识别数字
https://xiangyuecn.github.io/Recorder/assets/%E5%B7%A5%E5%85%B7-%E4%BB%A3%E7%A0%81%E8%BF%90%E8%A1%8C%E5%92%8C%E9%9D%99%E6%80%81%E5%88%86%E5%8F%91Runtime.html?jsname=teach.dtmf.decode_and_encode
flag6{590124}这是我识别出来的,特意拿手机按了一下,好像差不多
flag1
第二flag1,最简单
flag1{52pojiehappynewyear}
flag2
第三flag2,扫码就能获得,跟在url后面
flag2{878a48f2}
flagC
第四,视频中给出了一个地址2023challenge.52pojie.cn,并给出提醒与域名解析有关,添加hosts
成功打开
点击登录,一个input,现在是禁用的,打开developer tools删除disabled,输入uid,提交
哦吼吼,没这么简单
您不是 admin,你没有权限获取 flag
简单查看了一下源代码,并没有发现js文件,查看请求就只有cookie中的2023_challenge_jwt_token有点可疑,是jwt加密
来到https://jwt.io/解密
得到了
{ "uid": "906217",
"role": "user"
}
把user改为admin
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiI5MDYyMTciLCJyb2xlIjoiYWRtaW4ifQ.0n-chadlC7wCWuUvGid_9qBtO0G91IplcrNWgP-_Jpg
复制后修改cookie,方法就不赘述了,刷新,成功得到flagC。静态还没找到几个就给一个动态的 (悲
欢迎,admin。您的 flag 是 flagC{f1d40424},过期时间是 2023-01-29T14:50:00+08:00
flag7
第五,一筹莫展之际网页查看源代码发现了新的线索
const FLAG_LINE_A = '|01 1 001 1 001 1 01 1 0001 1 00001 01 1 001 1 1 001 1 0111 011 1 101100 1 1 0 10 1 011 0 01 0000 1 10000 001 1 01 1 0 011 0 00 10 011 0 010 100 1 1011 000 1 1 0 0 11 01111101==========|'; // 这里面藏着两个 flag 哦~
const FLAG_LINE_B = '|++++++++++[>++++++++++>++++++++++>+++++>++++++++++++++.++++++.>---.>-..>+++.-.>++.|';
const FLAG_LINE_A2 = FLAG_LINE_A.replaceAll(' ', '');
const FLAG_LINE_A_PARTS = Array.from(FLAG_LINE_A.matchAll(/. ?/g));
dns是124.232.185.97,看不出什么名堂
FLAG_LINE_A是一串二进制,https://www.binaryhexconverter.com/binary-to-ascii-text-converter 解码得到了flag7{5d06be63},两个只发现1个。呜呜
flag11
FLAG_LINE_B看不懂就拿去百度了,发现这是BrainFuck,通过https://www.nayuki.io/page/brainfuck-interpreter-javascript解码得到了flag11{63418de7}
flag4
本来已经放弃了,看到视频的创作团队点进了出题人的空间发现代码ZmxhZzR7OWNiOTExMTd9 base64解码得到flag4{9cb91117}
一些猜测
视频中有一段摩斯电码
背景应该有线索
视频结尾不知道在念什么