首页
社区
课程
招聘
[原创]看雪10月ctf2017 TSRC 第七题——9A82 pwn
发表于: 2017-11-7 11:18 6122

[原创]看雪10月ctf2017 TSRC 第七题——9A82 pwn

2017-11-7 11:18
6122

这题真难啊,折腾我好久,我都把整个游戏逆出来了,结果最后发现根本不用全部逆出来,哈哈。。不过没事,当作练习逆向了。。哈哈。。。

这道题我是没找到什么经典的缓冲区溢出啊格式化字符串啊double free啊UAF啊之类的洞。。。感觉我用的方法挺奇葩的。。。嗯。。。不知道跟大家用的方法一不一样。。。好了不废话了开始分析。。。

大概呢,就是作者自己mmap了一片内存,然后自己设计了一个chunk结构,然后申请内存空间都从这片mmap出来的内存申请。这个chunk结构的header有16字节,第二个一看就知道是chunk_size不说,关键是第一个,我一开始硬是没看出来这个QWORD是啥。。。

然后我们来看看game_start函数的部分代码(输入2 signup时)

v1 malloc 之后,会调用一个叫做dreflhs_rhs_withGC的函数,这个函数我前面一直没看懂,硬是盯了好久,才发现这其实是 带GC的 *参数1=参数2 的这么一个操作,所以chunk的第一个QWORD是一个类似引用计数的东西,我们跟进这个函数看看

这个代码讲起来有些复杂,总之大概就是*a1=a2,并且增加a2的计数,减少a1的计数,如果a1的计数变成0了,就以QWORD为单位遍历缓冲区里面的数,如果碰到在规定范围内的(*a1 <= 0x7FFFFFFFEFFFLL && *a1 > 0x400000LL),就对其进行处理,如rec_chunk函数所示。然而在这个范围内不一定是mmap中的地址,所以导致一个QWORD SHOOT,但是写入的数据只能是mem的值。
喔,还有就是我逆出来的结构体,供大家参考

所以什么时候会触发呢?就是sign第二次的时候,具体逻辑不说了。总之,如果前一个username转换成QWORD值时在范围内(*a1 <= 0x7FFFFFFFEFFFLL && *a1 > 0x400000LL)时,第二次sign就会导致[username]=mem。。。

所以怎么利用呢?好的,[任意地址]=mem,而且mem还会自增,还会有其他有效地址被存入mem!(所以有可能破坏mem中的shellcode) 这咋一看没什么用啊!我这种菜鸟,就卡在这想了好久!
最后根据我的不断实验,得出exploit方法:

注:

然后很尴尬的是,程序没有_exit的调用(主函数),所以找_exit的xref,发现唯一可能让他调用的是这里。。。

所以找个方法,把sign_infor->status->location_给污染了,就ok,实际上,如果动态跟一下的话,发现这个status就在cheat_buf的后面,而cheat有明显的溢出漏洞

300,够影响到status了,事实上,如果动态跟的话,我们会发现status的地址就在cheat_buf+0x98处(如果按照我都步骤做的话)。。。
然后就是构造payload了。。。

前面8个'A'是因为_exit的实际会跳转到cheat_buf+8处执行,动态跟一下就知道了,然后说说最后的那个0x605098,反正只要满载p->location不在范围内就好,我随便找的一个.data的地址,这个好像是mmap_initial?不记得了,哪个都一样。。。
shellcode基本上就是获取malloc函数地址,计算system地址,push (QWORD)"/bin/sh\x00"(刚好是8字节,哈哈),mov rdi,rsp, call system (伪代码,伪代码,请勿当真)
所以最后exp

_QWORD *__fastcall malloc_adjust(signed int a1)
{
  signed int v2; // [sp+Ch] [bp-4h]@3

  if ( a1 >= 0 && a1 > 16 )                     // >16
  {
    if ( a1 <= 16 || a1 > 48 )                  // >48
    {
      if ( a1 <= 48 || a1 > 80 )                // >80
        v2 = 400;                               // 80<x
      else
        v2 = 80;                                // 48<x<=80
    }
    else
    {
      v2 = 48;                                  // 16<size<=48
    }
  }
  else
  {
    v2 = 16;                                    // x<=16
  }
  return malloc_(v2);
}//这个malloc_adjust会根据输入调整一下实际分配的大小,就当他是对齐用的吧。。。
if ( v3 == 2 )
{
    puts("welcome to Playerunknown's Battlegrounds");
    puts("First,you need set your username and password");
    v1 = malloc_adjust(48);
    dreflhs_rhs_withGC((_QWORD **)&sign_infor, v1);// collapse
    puts("input your username");
    getstr(sign_infor->username, 0x10LL);
    puts("input your password");
    getstr(sign_infor->password, 0x10LL);
    puts("Second,you need create a character and give him a name");
    v2 = malloc_adjust(56);
    dreflhs_rhs_withGC((_QWORD **)&sign_infor->status, v2);
    sign_infor->status->health = 100LL;
    sign_infor->status->capacity = 100LL;
    sign_infor->status->stamina = 100LL;
    puts("input your character's name");
    getstr(sign_infor->status->name, 0x10LL);
    puts("all is ok");
}
// *lhs=rhs
_QWORD *__fastcall dreflhs_rhs_withGC(_QWORD **pointer, void *mem_frommymalloc)
{
  _QWORD *chunk_mem; // rax@2
  _QWORD *chunk; // rax@4
  _QWORD *result; // rax@5

  if ( mem_frommymalloc )
  {
    chunk_mem = minus_16(mem_frommymalloc);
    incre_ref(chunk_mem);
  }
  if ( *pointer )
  {
    chunk = minus_16(*pointer);
    reduce_ref(chunk);                          // collapse
  }
  result = pointer;
  *pointer = mem_frommymalloc;
  return result;
}
__int64 __fastcall is_deref_a_inrange(_QWORD *a1)
{
  return *a1 <= 0x7FFFFFFFEFFFLL && *a1 > 0x400000LL;
}
_DWORD *__fastcall ret_addr_of_first_addr(_QWORD *chunk, signed __int64 *pi)
{
  signed __int64 i; // [sp+18h] [bp-18h]@3
  signed __int64 size; // [sp+20h] [bp-10h]@3
  _QWORD *mem; // [sp+28h] [bp-8h]@3

  if ( !chunk )
    exit(0);
  mem = chunk + 2;
  size = (chunk[1] - 16LL) / 8;
  for ( i = *pi; i < size; ++i )
  {
    *pi = i;
    if ( (unsigned __int8)is_deref_a_inrange(&mem[i]) )
      return &mem[i];
  }
  return 0LL;
}

// also, reflect mem to chunk[2](data part)
_QWORD *__fastcall rec_chunk(_QWORD *chunk)
{
  _QWORD *result; // rax@3

  if ( !mem )
    mem = malloc_adjust(4);
  chunk[2] = mem;//任意chunk[2]可以被我们控制,会被赋值为mem的值,QWORD SHOOT here!!!
  *mem = chunk;                        // 可能overflow,但我没用这个
  result = mem + 1;
  ++mem;
  return result;
}
__int64 __fastcall reduce_ref(_QWORD *chunk)
{
  _QWORD *chunk_1; // rax@3
  __int64 i; // [sp+10h] [bp-20h]@1
  _QWORD *chunk_; // [sp+18h] [bp-18h]@1
  _QWORD **p_elem; // [sp+20h] [bp-10h]@2
  __int64 v6; // [sp+28h] [bp-8h]@1

  v6 = *MK_FP(__FS__, 40LL);
  i = 0LL;
  chunk_ = chunk;
  --*chunk;
  if ( !*chunk_ )                               // 如果引用计数变成0
  {
    while ( 1 )
    {
      p_elem = (_QWORD **)ret_addr_of_first_addr(chunk, &i);
      if ( p_elem == 0LL )                      // 如果在chunk中已经没有有效地址了
        break;
      ++i;                                      // 增加i并且做下次循环
      chunk_1 = minus_16(*p_elem);              // 如果 *pmem 是有效地址(在指定范围中),但不一定是在mmap的堆中, 也会把它当作mmap中的chunk,进行rec_chunk的调用
      rec_chunk(chunk_1);                       // 它被当成了chunk,但不一定是mmap中的chunk(0x41414141-16)
    }
    rec_chunk(chunk_);
  }
  return *MK_FP(__FS__, 40LL) ^ v6;
}

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 1
支持
分享
最新回复 (22)
雪    币: 2375
活跃值: (433)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
整个逆出来,楼主花了多久?
2018-3-27 05:30
0
雪    币: 5676
活跃值: (1303)
能力值: ( LV17,RANK:1185 )
在线值:
发帖
回帖
粉丝
3
petersonhz 整个逆出来,楼主花了多久?
逆出来几个小时吧,想如何利用想了比较久
2018-3-27 06:13
0
雪    币: 2375
活跃值: (433)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
holing 逆出来几个小时吧,想如何利用想了比较久
能逆东西,是否可以去病毒公司了呢
2018-3-27 13:52
0
雪    币: 5676
活跃值: (1303)
能力值: ( LV17,RANK:1185 )
在线值:
发帖
回帖
粉丝
5
petersonhz 能逆东西,是否可以去病毒公司了呢[em_1]
还需要一些windows的知识吧
2018-3-29 18:16
0
雪    币: 2375
活跃值: (433)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
holing 还需要一些windows的知识吧
病毒公司招人是不是很少
2018-3-29 21:36
0
雪    币: 5676
活跃值: (1303)
能力值: ( LV17,RANK:1185 )
在线值:
发帖
回帖
粉丝
7
petersonhz 病毒公司招人是不是很少[em_15]
我不知道。。。现在还没有工作。。。
2018-3-30 01:48
0
雪    币: 2375
活跃值: (433)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
holing 我不知道。。。现在还没有工作。。。
你现在整天捣鼓病毒么
2018-5-28 00:37
0
雪    币: 5676
活跃值: (1303)
能力值: ( LV17,RANK:1185 )
在线值:
发帖
回帖
粉丝
9
petersonhz 你现在整天捣鼓病毒么[em_1]
没有。。。
2018-5-28 00:40
0
雪    币: 2375
活跃值: (433)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
holing 没有。。。
你给自己破过几个软件呢
2018-5-28 00:43
0
雪    币: 5676
活跃值: (1303)
能力值: ( LV17,RANK:1185 )
在线值:
发帖
回帖
粉丝
11
petersonhz 你给自己破过几个软件呢[em_1]
你为啥总是喜欢问这些奇怪的问题。。。
2018-5-28 00:47
0
雪    币: 2375
活跃值: (433)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
holing 你为啥总是喜欢问这些奇怪的问题。。。
逆向不是可以拿来破软件么
2018-5-28 00:49
0
雪    币: 5676
活跃值: (1303)
能力值: ( LV17,RANK:1185 )
在线值:
发帖
回帖
粉丝
13
petersonhz 逆向不是可以拿来破软件么[em_20]
可是,我破过几个软件,跟你有什么关系呢。。。
2018-5-28 00:50
0
雪    币: 2375
活跃值: (433)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
holing 可是,我破过几个软件,跟你有什么关系呢。。。
不会把破了的软件借我用用么
2018-5-28 00:53
0
雪    币: 5676
活跃值: (1303)
能力值: ( LV17,RANK:1185 )
在线值:
发帖
回帖
粉丝
15
petersonhz 不会把破了的软件借我用用么[em_15]
你这个吾爱破解一堆啊,比我破的好的多了去了。。。
2018-5-28 00:54
0
雪    币: 2375
活跃值: (433)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
holing 你这个吾爱破解一堆啊,比我破的好的多了去了。。。
你会外挂么
2018-5-28 00:58
0
雪    币: 5676
活跃值: (1303)
能力值: ( LV17,RANK:1185 )
在线值:
发帖
回帖
粉丝
17
petersonhz 你会外挂么[em_15]
不会
2018-5-28 01:06
0
雪    币: 2375
活跃值: (433)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
holing 不会
安卓逆向搞不:)
2018-5-28 08:43
0
雪    币: 5676
活跃值: (1303)
能力值: ( LV17,RANK:1185 )
在线值:
发帖
回帖
粉丝
19
petersonhz 安卓逆向搞不:)
不会,不搞
2018-5-28 23:26
0
雪    币: 2375
活跃值: (433)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
holing 不会,不搞
开发搞么?
2018-5-29 01:20
0
雪    币: 5676
活跃值: (1303)
能力值: ( LV17,RANK:1185 )
在线值:
发帖
回帖
粉丝
21
不会,不搞
2018-5-29 06:16
0
雪    币: 11716
活跃值: (133)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
holing 不会,不搞
大佬脾气是真的好..........
2018-6-11 23:06
0
雪    币: 870
活跃值: (2264)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
赞!写的好
2018-7-22 23:31
0
游客
登录 | 注册 方可回帖
返回
//