Skip to content

Instantly share code, notes, and snippets.

@astarasikov
Created March 5, 2014 15:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save astarasikov/9369538 to your computer and use it in GitHub Desktop.
Save astarasikov/9369538 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <signal.h>
#include <execinfo.h>
#include <ucontext.h>
#include <stdlib.h>
#include <sys/mman.h>
#define PAGE_SIZE 4096
#define PAGE_MASK (PAGE_SIZE - 1)
#define BAD_DEBUG
#define OPCODE_SVC0 0xef000000
#define OPCODE_RESERVED -1UL
extern void raw_write(int fd, char *str, int len) {
register int _fd asm ("r0");
register char *_str asm("r1");
register int _len asm("r2");
_fd = fd;
_str = str;
_len = len;
asm volatile(
"mov r7, #4\n"
"svc #0\n"
::: "r0", "r1", "r2", "r7", "memory"
);
}
extern void bad_function() {
raw_write(1, "hello", 6);
raw_write(1, "poop", 5);
}
static void fuckup(void) {
unsigned *ptr = (unsigned*)raw_write;
while (ptr < ((unsigned*)raw_write) + PAGE_SIZE) {
if (*ptr == OPCODE_SVC0) {
#ifdef BAD_DEBUG
fprintf(stderr, "patching @%p\n", ptr);
fflush(stderr);
#endif
*ptr = OPCODE_RESERVED;
break;
/* funny fact: I accidentally patched the
* sa_restore_handler which crashed with SIGSEGV
* giving no chance to patch back in SIGILL
*/
}
ptr++;
}
}
static void unfuckup(void) {
unsigned *ptr = (unsigned*)raw_write;
while (ptr < ((unsigned*)raw_write) + PAGE_SIZE) {
if (*ptr == OPCODE_RESERVED) {
#ifdef BAD_DEBUG
fprintf(stderr, "unpatching @%p\n", ptr);
fflush(stderr);
#endif
*ptr = OPCODE_SVC0;
break;
}
ptr++;
}
}
static void my_sh(int signo, siginfo_t *si, void *data) {
#ifdef BAD_DEBUG
fprintf(stderr, "signal %d\n", signo);
fflush(stderr);
#endif
unfuckup();
ucontext_t *uc = (ucontext_t*)data;
struct sigcontext *ctx = &(((ucontext_t*)uc)->uc_mcontext);
//ctx->arm_pc += 4;
}
int main(int argc, char **argv) {
void *func = 0;
struct sigaction sa = {};
sa.sa_flags = /* SA_ONSTACK |*/ SA_RESTART | SA_SIGINFO;
sa.sa_sigaction = my_sh;
sigemptyset(&sa.sa_mask);
sigaction(SIGILL, &sa, NULL);
fprintf(stderr, "in main, about to fuckup\n");
fflush(stderr);
func = (void*)(((unsigned long)raw_write) & ~PAGE_MASK);
fprintf(stderr, "gotta mprotect @%p\n", func);
fflush(stderr);
/* ok, let's make .text writable */
if (mprotect(func, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC) < 0)
{
perror("mprotect");
exit(-1);
}
fuckup();
fprintf(stderr, "In main, about to call bad routine\n");
fflush(stderr);
bad_function();
fprintf(stderr, "I'm alive\n");
fflush(stderr);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment