【前言】
其实一直在关注52pojie 大概零几年注册id学习了一会crackme就停了
去年重新上线 作为新手也是第一次知道还有这个活动 大概是初八在公众号刷到,看着满满的CB 忍不住要来试一下
下面是我个人对于解题过程的记录,可以看出有许多不熟悉的地方,供大家避坑~
请大家一定要多看几位大神的解题帖子,跟着他们的思路走,以达到事半功倍的效果。
【正文】
一、首先是Windows初级题。
先运行了一下,提示长度错误。然后就一个一个长度试,得到29个字符换成提示“Wong,please try again."
启动x32dbg,载入程序进行调试
点击字符串工具,找到几个提示信息下断点
再次运行,可以看到有个比较,确认是长度29
继续往下会断在Wrong那里。往上翻了一会儿,看到一个“Success”,并且上面有个cmp的比较
下断电跟踪几次 发现bl里依次是 f、l、a、g等字符,前面是我输入的字符 确认是和正确答案的字符串比较
突然想到能不能直接把答案输出来 于是在cmp上按空格汇编,改成mov
同时把下面的jne全部改成nop不跳转
然后右键edx,在内存中显示
接下来就是取消cmp处的断点,F9运行,可以看到内存中直接出现了flag
程序也输出了Success
二、Windows中级题(未解出)
又试了一下中级题,用x64dbg打开不能调试 先用老工具peid查没查到 换用DIE查到是UPX+modified
于是上论坛找类似crackme的解法,学习了RSP大法、scylla大法和固定ASLR大法,终于得到一个可以运行的去壳程序
然而进x64dbg还是闪退(没有其它插件) 一番折腾后 改用附加方式进行调试
断GetDlgItemTextW,找到获取uid和key的代码,又上IDA分析
无奈加密过程有点复杂 放弃
【感想】由此题学到更多脱壳和64位程序的分析思路
三、Android初级题1、2
特意看了几篇题目给的教程(时间紧没全部看完)
一边搭建模拟器环境 找出以前的AndroidKiller
第1题直接暴力连点器。。没怎么分析
第2题用killer解包,分析代码,发现有个校验签名的函数,修改代码后重新打包,发现点击的按钮没有了
折腾了一阵还是没有结果
又找到教程中的jadx工具解出代码
分析后终于发现了加密算法代码,于是又从论坛上学到一个在线java调试的方法
将原来的代码进行了一些修改(对java不熟悉 可能有不对的地方 但是结果对了) 弄上去运行算出key
[Java] 纯文本查看 复制代码 import java.util.Base64;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/* Online Java Compiler and Editor */
class C0838B {
public static String encode(String str) {
int length = str.length();
char[] cArr = new char[length];
int i = length - 1;
while (i >= 0) {
int i2 = i - 1;
cArr[i] = (char) (str.charAt(i) ^ '5');
if (i2 < 0) {
break;
}
i = i2 - 1;
cArr[i2] = (char) (str.charAt(i2) ^ '2');
}
return new String(cArr);
}
}
final class C0839C {
public static final C0839C INSTANCE = new C0839C();
private C0839C() {
}
private final char cipher(char c, int i) {
char c2 = Character.isUpperCase(c) ? 'A' : 'a';
return (char) (((char) (((((char) (c - c2)) + (i % 26)) + 26) % 26)) + c2);
}
public final String cipher(String str, int i) {
StringBuilder sb = new StringBuilder();
int length = str.length();
for (int i2 = 0; i2 < length; i2++) {
if ( ((int) str.charAt(i2) >= 65) && ( (int)str.charAt(i2)<= 90)) {
sb.append(cipher(str.charAt(i2), i));
} else if ( ((int)str.charAt(i2) < 97) || ((int)str.charAt(i2) > 122) ) {
sb.append(str.charAt(i2));
} else {
sb.append(cipher(str.charAt(i2), i));
}
}
String sb2 = sb.toString();
return sb2;
}
}
final class Base64Utils {
public static final Base64Utils INSTANCE = new Base64Utils();
final Base64.Decoder decoder = Base64.getDecoder();
final Base64.Encoder encoder = Base64.getEncoder();
private Base64Utils() {
}
public final byte[] encodeToBytes(byte[] bArr) {
byte[] encode = encoder.encode(bArr);
return encode;
}
public final String encodeToString(byte[] bArr) {
String encodeToString = encoder.encodeToString(bArr);
return encodeToString;
}
public final byte[] decode(byte[] bArr) {
byte[] decode = decoder.decode(bArr);
return decode;
}
public final byte[] decode(String str) {
byte[] decode = decoder.decode(str);
return decode;
}
}
final class MD5Utils {
public static final MD5Utils INSTANCE = new MD5Utils();
private MD5Utils() {
}
public final String MD5(String sourceStr) {
try {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
byte[] bytes = sourceStr.getBytes();
messageDigest.update(bytes);
byte[] digest = messageDigest.digest();
StringBuffer stringBuffer = new StringBuffer("");
int length = digest.length;
for (int i = 0; i < length; i++) {
int i2 = digest[i];
if (i2 < 0) {
i2 += 256;
}
if (i2 < 16) {
stringBuffer.append("0");
}
stringBuffer.append(Integer.toHexString(i2));
}
String stringBuffer2 = stringBuffer.toString();
return stringBuffer2;
} catch (Exception e) {
System.out.println(e);
return "";
}
}
}
public class Test
{
public static void main(String[] args)
{
String str = "11111";
String str1;
String str2 = "flag{123}";
String str3;
if ( 1==1 ){
C0839C c0839c = C0839C.INSTANCE;
MD5Utils mD5Utils = MD5Utils.INSTANCE;
Base64Utils base64Utils = Base64Utils.INSTANCE;
String encode = C0838B.encode(str + "Wuaipojie2023");
System.out.println("encode:"+encode);
byte[] bytes = encode.getBytes();
str1 = base64Utils.encodeToString(bytes);
System.out.println("B64:"+str1);
str3 = c0839c.cipher(mD5Utils.MD5(str1), 5);
System.out.println("final:"+str3);
}
}
}
【感受】学习到了新的工具jadx使用,新的java代码在线调试方法
四、Android中级题(未解出)
先是运行后要求大声喊 然而声音最高到90dB
jadx看代码需要到100dB
又学习了一会儿教程 搭建起frida环境,使用hook方法修改volume为直接返回100
运行显示快去找flag
再次分析代码,发现write_img代码,写了一个aes.png文件
到app目录中找到文件打开,似乎是一串b64加密的数据,直接b64解密后是乱码,不是png数据
又查看代码,发现有从52pj.so中引入decrypt、encrypt和get_RealKey三个函数
并找到一个可疑的16位字符串,尝试用hook代码进行解密,数据仍然不对,放弃
【感受】学习到frida工具的使用及hook代码的编写,了解了AES加密的知识
五、Web题
这道题是我觉得很有趣的题目,涉及的知识和方法很广泛
1、首先按键音能听出来是6个数字,利用百度DTMF频率,再用goldwave频谱中的Waterfall图,
将频率调整到600-1500Hz之间 根据每个音的高低频率解出数字,得到flag6
*但这里我却完美地错过了flag8,因为flag8的频率在4kHz-8kHz之间,导致我的图上没显示出来
2、第二个是直接显示在视频上的flag1
3、第三个解出来的是摩斯密码flag5,这个谍战剧看多了都比较熟
4、第四个解出来的是二维码,找个在线识别工具可识别flag2
5、第五个解出来的是视频右下角的水印,iodj3经过分析发现就是flag3
6、第六个解出来的是flag7,就是上面那串01100110...(先是反复数0101 后来发现在隐藏网页中有代码,不用数)
7、第七个解出来的是最后那段语音,听着怪怪的像倒放 用goldwave反向一下,能听到flag9
到这里我基本上没什么头绪了,但是又多看了几遍视频,发现了线索
8、第八个解出来的是flag11,看下面一堆++++号 百度一下发现疑似是一种brainf**k的加密方式 找个在线工具解出来了
静态中只找到这八个了,剩下的4、8、10、12没找到
9、然后是动态码
根据提示,将视频显示的网站用hosts解析到IP上,成功进入网站,发现登录后无权限
搜索cookie发现jwt_token,百度学习一番,来到jwt.io解密发现"role":"user"字样,将user改为admin后改掉cookie,拿到flagC
接下来分析源代码、HTTP头等各种信息,突然发现在一个响应头中有flagA字样,不过后面提示header中没有uid信息
用python的urllib构造一个header带uid信息的请求过去,拿到flagA
反复研究源码 看到提示“从DNS中找到一些信息” 于是学习了一下DNS解析的知识
使用nslookup -qt=txt 2023challenge.52pojie.cn 4.4.4.4找到提示
[Shell] 纯文本查看 复制代码
非权威应答:
2023challenge.52pojie.cn text =
""_52pojie_2023_happy_new_year=flagB{substr(md5(uid+\"_happy_new_year_\"+floor(timestamp/600)),0,8)}""
使用python编辑代码并运行,得到flagB
[Python] 纯文本查看 复制代码
import hashlib, time, math
hashlib.md5(('1581363_happy_new_year_'+str(math.floor(time.time()/600))).encode('utf8')).hexdigest()[0:8]
由于每个难度的flag都不够,最后只有在难度下调后才提交成功
【感受】通过Web题,了解了更多的信息加密和传递方式,认识了Web中使用的一些信息传递和验证技术。
总的说来,参与此次活动总体是快乐的,过程是紧张的,学习是充实的,感谢论坛和各位的付出。
祝大家2023新年大吉!
|