Created
February 14, 2018 09:34
-
-
Save un4ckn0wl3z/b69eeed74bc0058775ad159d053637a8 to your computer and use it in GitHub Desktop.
RETriforce Files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
push rbp | |
mov rbp,rsp | |
sub rsp,0x40 | |
mov DWORD PTR [rbp-0x34],edi | |
mov QWORD PTR [rbp-0x40],rsi | |
mov QWORD PTR [rbp-0x30],0x0 | |
mov QWORD PTR [rbp-0x28],0x0 | |
mov QWORD PTR [rbp-0x20],0x0 | |
mov QWORD PTR [rbp-0x18],0x0 | |
mov BYTE PTR [rbp-0x30],0x66 | |
mov BYTE PTR [rbp-0x2f],0x6c | |
mov BYTE PTR [rbp-0x2e],0x61 | |
mov BYTE PTR [rbp-0x2d],0x67 | |
mov BYTE PTR [rbp-0x2c],0x7b | |
mov BYTE PTR [rbp-0x2b],0x14 | |
movzx eax,BYTE PTR [rbp-0x2b] | |
mov edx,eax | |
mov eax,edx | |
shl eax,0x2 | |
add eax,edx | |
mov BYTE PTR [rbp-0x2b],al | |
movzx eax,BYTE PTR [rbp-0x2b] | |
sub eax,0x1 | |
mov BYTE PTR [rbp-0x2b],al | |
mov BYTE PTR [rbp-0x2a],0x6e | |
movzx eax,BYTE PTR [rbp-0x2a] | |
xor eax,0x17 | |
mov BYTE PTR [rbp-0x2a],al | |
mov BYTE PTR [rbp-0x29],0x62 | |
movzx eax,BYTE PTR [rbp-0x29] | |
sar al,0x2 | |
mov BYTE PTR [rbp-0x29],al | |
movzx eax,BYTE PTR [rbp-0x29] | |
shl eax,0x2 | |
mov BYTE PTR [rbp-0x29],al | |
movzx eax,BYTE PTR [rbp-0x29] | |
add eax,0x2 | |
mov BYTE PTR [rbp-0x29],al | |
mov BYTE PTR [rbp-0x28],0x30 | |
movzx eax,BYTE PTR [rbp-0x28] | |
movsx eax,al | |
shl eax,0x2 | |
mov BYTE PTR [rbp-0x28],al | |
movzx eax,BYTE PTR [rbp-0x28] | |
or eax,0xf | |
mov BYTE PTR [rbp-0x28],al | |
movzx eax,BYTE PTR [rbp-0x28] | |
add eax,0x64 | |
mov BYTE PTR [rbp-0x28],al | |
mov BYTE PTR [rbp-0x27],0xe | |
mov DWORD PTR [rbp-0x4],0x0 | |
jmp 0x4005f7 | |
movzx eax,BYTE PTR [rbp-0x27] | |
add eax,0x1 | |
mov BYTE PTR [rbp-0x27],al | |
add DWORD PTR [rbp-0x4],0x1 | |
cmp DWORD PTR [rbp-0x4],0x63 | |
jle 0x4005e9 | |
mov BYTE PTR [rbp-0x26],0xff | |
movzx eax,BYTE PTR [rbp-0x26] | |
lea edx,[rax+0x3] | |
test al,al | |
cmovs eax,edx | |
sar al,0x2 | |
mov BYTE PTR [rbp-0x26],al | |
movzx eax,BYTE PTR [rbp-0x26] | |
sar al,0x2 | |
mov BYTE PTR [rbp-0x26],al | |
movzx eax,BYTE PTR [rbp-0x26] | |
add eax,0x73 | |
mov BYTE PTR [rbp-0x26],al | |
mov BYTE PTR [rbp-0x25],0xff | |
movzx eax,BYTE PTR [rbp-0x25] | |
add eax,0x4 | |
mov BYTE PTR [rbp-0x25],al | |
movzx eax,BYTE PTR [rbp-0x25] | |
mov edx,eax | |
mov eax,edx | |
shl eax,0x3 | |
add eax,edx | |
shl eax,0x2 | |
add eax,edx | |
mov BYTE PTR [rbp-0x25],al | |
movzx eax,BYTE PTR [rbp-0x25] | |
add eax,0xa | |
mov BYTE PTR [rbp-0x25],al | |
movzx eax,BYTE PTR [rbp-0x25] | |
sub eax,0x9 | |
mov BYTE PTR [rbp-0x25],al | |
mov BYTE PTR [rbp-0x24],0x3 | |
movzx eax,BYTE PTR [rbp-0x24] | |
movsx eax,al | |
shl eax,0x4 | |
mov BYTE PTR [rbp-0x24],al | |
movzx eax,BYTE PTR [rbp-0x24] | |
or eax,0x4 | |
mov BYTE PTR [rbp-0x24],al | |
mov BYTE PTR [rbp-0x23],0x14 | |
movzx eax,BYTE PTR [rbp-0x23] | |
mov edx,eax | |
mov eax,edx | |
shl eax,0x2 | |
add eax,edx | |
mov BYTE PTR [rbp-0x23],al | |
movzx eax,BYTE PTR [rbp-0x23] | |
sub eax,0x1 | |
mov BYTE PTR [rbp-0x23],al | |
mov BYTE PTR [rbp-0x22],0x30 | |
movzx eax,BYTE PTR [rbp-0x22] | |
movsx eax,al | |
shl eax,0x2 | |
mov BYTE PTR [rbp-0x22],al | |
movzx eax,BYTE PTR [rbp-0x22] | |
or eax,0xf | |
mov BYTE PTR [rbp-0x22],al | |
movzx eax,BYTE PTR [rbp-0x22] | |
add eax,0x64 | |
mov BYTE PTR [rbp-0x22],al | |
movzx eax,BYTE PTR [rbp-0x23] | |
mov BYTE PTR [rbp-0x21],al | |
movzx eax,BYTE PTR [rbp-0x21] | |
sub eax,0x4 | |
mov BYTE PTR [rbp-0x21],al | |
mov BYTE PTR [rbp-0x20],0x14 | |
movzx eax,BYTE PTR [rbp-0x20] | |
mov edx,eax | |
mov eax,edx | |
shl eax,0x2 | |
add eax,edx | |
mov BYTE PTR [rbp-0x20],al | |
movzx eax,BYTE PTR [rbp-0x20] | |
sub eax,0x1 | |
mov BYTE PTR [rbp-0x20],al | |
mov BYTE PTR [rbp-0x1f],0x3 | |
movzx eax,BYTE PTR [rbp-0x1f] | |
movsx eax,al | |
shl eax,0x4 | |
mov BYTE PTR [rbp-0x1f],al | |
movzx eax,BYTE PTR [rbp-0x1f] | |
or eax,0x4 | |
mov BYTE PTR [rbp-0x1f],al | |
mov BYTE PTR [rbp-0x1e],0x64 | |
movzx eax,BYTE PTR [rbp-0x1e] | |
add eax,0xa | |
mov BYTE PTR [rbp-0x1e],al | |
movzx eax,BYTE PTR [rbp-0x1e] | |
sub eax,0x1 | |
mov BYTE PTR [rbp-0x1e],al | |
mov BYTE PTR [rbp-0x1d],0xff | |
movzx eax,BYTE PTR [rbp-0x1d] | |
add eax,0x4 | |
mov BYTE PTR [rbp-0x1d],al | |
movzx eax,BYTE PTR [rbp-0x1d] | |
mov edx,eax | |
mov eax,edx | |
shl eax,0x3 | |
add eax,edx | |
shl eax,0x2 | |
add eax,edx | |
mov BYTE PTR [rbp-0x1d],al | |
movzx eax,BYTE PTR [rbp-0x1d] | |
add eax,0xa | |
mov BYTE PTR [rbp-0x1d],al | |
movzx eax,BYTE PTR [rbp-0x1d] | |
sub eax,0x9 | |
mov BYTE PTR [rbp-0x1d],al | |
mov BYTE PTR [rbp-0x1c],0x7d | |
lea rax,[rbp-0x30] | |
mov rdi,rax |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
from keystone import * | |
from capstone import * | |
from capstone.x86 import * | |
from unicorn import * | |
from unicorn.x86_const import * | |
from struct import pack | |
from binascii import hexlify, unhexlify | |
import argparse | |
def read_file(fileName): | |
f = open(fileName, "r") | |
code = f.read() | |
f.close() | |
return code | |
def print_registers(emu): | |
rax = emu.reg_read(UC_X86_REG_RAX) | |
rbx = emu.reg_read(UC_X86_REG_RBX) | |
rcx = emu.reg_read(UC_X86_REG_RCX) | |
rdx = emu.reg_read(UC_X86_REG_RDX) | |
rsi = emu.reg_read(UC_X86_REG_RSI) | |
rdi = emu.reg_read(UC_X86_REG_RDI) | |
rsp = emu.reg_read(UC_X86_REG_RSP) | |
rbp = emu.reg_read(UC_X86_REG_RBP) | |
rip = emu.reg_read(UC_X86_REG_RIP) | |
r8 = emu.reg_read(UC_X86_REG_R8) | |
r9 = emu.reg_read(UC_X86_REG_R9) | |
r10 = emu.reg_read(UC_X86_REG_R10) | |
r11 = emu.reg_read(UC_X86_REG_R11) | |
r12 = emu.reg_read(UC_X86_REG_R12) | |
r13 = emu.reg_read(UC_X86_REG_R13) | |
r14 = emu.reg_read(UC_X86_REG_R14) | |
r15 = emu.reg_read(UC_X86_REG_R15) | |
print("--------------------------------------------------------------------------------") | |
print("/////////////////////////////// REGISTER STATE /////////////////////////////////") | |
print("--------------------------------------------------------------------------------") | |
print("rax = 0x%016x rdx = 0x%016x rsp = 0x%016x" % (rax, rdx, rsp)) | |
print("rbx = 0x%016x rsi = 0x%016x rbp = 0x%016x" % (rbx, rsi, rbp)) | |
print("rcx = 0x%016x rdi = 0x%016x rip = 0x%016x" % (rax, rdi, rip)) | |
print("r8 = 0x%016x r9 = 0x%016x r10 = 0x%016x" % (r8, r9, r10)) | |
print("r11 = 0x%016x r12 = 0x%016x r13 = 0x%016x" % (r11, r12, r13)) | |
print("r14 = 0x%016x r15 = 0x%016x" % (r14, r15)) | |
print("--------------------------------------------------------------------------------") | |
def hook_code(emu, address, size, user_data): | |
# user_data contains optional data specified by the caller | |
# I've included the capstone instance (cap) in a list | |
cap = user_data[0] | |
# read the opcodes for this instruction | |
ocbytes = emu.mem_read(address, size) | |
opcodes = hexlify(ocbytes) | |
try: | |
if cap.detail: | |
for inst in cap.disasm(bytes(ocbytes), size): | |
print("0x%08x: %s\t%s\t%s" % (address, opcodes.ljust(15), inst.mnemonic, inst.op_str)) | |
# get and print some detailed information about this instruction | |
sm_operlen = len(inst.operands) | |
print(" Operands: %d" % sm_operlen) | |
# if instructions has operands, get more details | |
if sm_operlen > 0: | |
c = -1 | |
for i in inst.operands: | |
c += 1 | |
if i.type == X86_OP_MEM: | |
print(" Type: Memory Operation") | |
# see if the memory operation has a base | |
if i.mem.base != 0: | |
print(" Operand %d mem.base: REG = %s" % (c, inst.reg_name(i.mem.base))) | |
# get memory access type | |
# Note: if you are not on the Capstone "NEXT BRANCH" i.access will fail! | |
# See this: https://github.com/aquynh/capstone/wiki/Next-branch | |
if i.access == CS_AC_READ: | |
print(" Operand %d Access: READ\n" % (c)) | |
elif i.access == CS_AC_WRITE: | |
print(" Operand %d Access: WRITE\n" % (c)) | |
elif i.access == CS_AC_READ | CS_AC_WRITE: | |
print(" Operand %d Access: READ | WRITE\n" % (c)) | |
else: | |
print(" Operand %d Access: UNKNOWN\n" % (c)) | |
print("") | |
else: | |
for (cs_address, cs_size, cs_mnemonic, cs_opstr) in cap.disasm_lite(str(ocbytes), address): | |
print("0x%08x:\t%s\t%s" % (cs_address, cs_mnemonic, cs_opstr)) | |
except CsError as e: | |
print("CAPSTONE ERROR: %s" % e) | |
def main(): | |
BASE_ADDRESS = 0x0000000000400526 | |
try: | |
# Initialize Keystone, Capstone, and Unicorn | |
kst = Ks(KS_ARCH_X86, KS_MODE_64) | |
cap = Cs(CS_ARCH_X86, CS_MODE_64) | |
emu = Uc(UC_ARCH_X86, UC_MODE_64) | |
# Emable detailed disassembly if requested by user | |
# Allows us to get semantics about each instruction | |
if args.detail: | |
cap.detail = True | |
# Read the assembly code from the user specified file | |
ASM_CODE = read_file(args.assembly_file) | |
# Assemble our challenge assembly to machine code with Keystone | |
try: | |
encoding, count = kst.asm(ASM_CODE, BASE_ADDRESS) | |
MACHINE_CODE = "" | |
for opcode in encoding: | |
MACHINE_CODE += pack("B", opcode) | |
except KsError as e: | |
# ruh-roh, we cannot recover from an assembly error, bail out | |
print("KEYSTONE ERROR: %s" % e) | |
exit() | |
# Hook each instruction so we can print them with Capstone | |
emu.hook_add(UC_HOOK_CODE, hook_code, [cap]) | |
# Create 2MB of memory at the closest page boundary for the code | |
emu.mem_map((BASE_ADDRESS/0x1000)*0x1000, 2 * 1024 * 1024) | |
# Write our challenge code to the base address | |
emu.mem_write(BASE_ADDRESS, MACHINE_CODE) | |
# create stack space for the code to use | |
# location is completely arbitrary, size depends on code being emulated | |
# do not "collide" with your executable code (MACHINE_CODE) space! | |
STACK_START = 0x0000000000200000 | |
STACK_SIZE = 0x0000000000010000 | |
emu.mem_map(STACK_START - STACK_SIZE, STACK_SIZE) | |
# set stack pointer and base pointer to the location of our stack | |
emu.reg_write(UC_X86_REG_RSP, STACK_START) | |
emu.reg_write(UC_X86_REG_RBP, STACK_START) | |
# setting RIP is not required, we do it so the regitser print isn't misleading | |
# emu_start sets RIP for us | |
emu.reg_write(UC_X86_REG_RIP, BASE_ADDRESS) | |
# Print the starting register state | |
print_registers(emu) | |
# Run emulation from the start of code to the end | |
# Registers and memory initialize to ZERO (0x0000000000000000) | |
emu.emu_start(BASE_ADDRESS, BASE_ADDRESS + len(MACHINE_CODE)) | |
# Print the flag. We know RAX and RDI contain a pointer to the flag on the stack | |
rax = emu.reg_read(UC_X86_REG_RAX) | |
# read 40 bytes from the flag pointer (size is arbitrarily chosen, flag ends up being 21 bytes) | |
flag = emu.mem_read(rax, 40) | |
# print the final register state | |
print_registers(emu) | |
# print the flag | |
print("Flag: %s" % flag) | |
except UcError as e: | |
print("UNICORN ERROR: %s" % e) | |
if __name__ == "__main__": | |
# argument parsing | |
parser = argparse.ArgumentParser(description="RETriforce: Keystone, Capstone, Unicorn Example") | |
# required arguments | |
parser.add_argument('assembly_file', action='store', help='x86_64 assembly file') | |
# optional arguments | |
parser.add_argument('--detail', action='store_true', help='print semantic information about instructions') | |
args = parser.parse_args() | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FROM ubuntu:16.04 | |
## Helpful commands | |
# >> Build the docker container | |
# docker build -t retriforce . | |
# >> Run the docker container, mapping a directory into the container | |
# docker run --rm -it -v "<HOST_SHARE>:<GUEST_DIR>" retriforce | |
## Tunables | |
ENV UNICORNVER 0.9 | |
#ENV CAPSTONEVER 3.0.4 | |
ENV CAPSTONEVER next | |
ENV KEYSTONEVER 0.9.1 | |
## Checkout new versions if you're interested: | |
# http://www.unicorn-engine.org/download/ | |
# http://www.capstone-engine.org/download.html | |
# http://www.keystone-engine.org/download/ | |
## Prepare dependencies | |
RUN apt-get update -y | |
RUN apt-get install -y python-dev libglib2.0-dev wget less vim sed cmake time python-pip | |
RUN apt-get install -y lib32stdc++-4.8-dev libc6-dev-i386 | |
RUN pip install --upgrade pip | |
########################################################### | |
## Install the Unicorn Engine | |
# Get the Unicorn-Engine sources | |
WORKDIR /usr/src | |
RUN wget https://github.com/unicorn-engine/unicorn/archive/$UNICORNVER.tar.gz && tar -xzf $UNICORNVER.tar.gz | |
# Build the Unicorn-Engine | |
WORKDIR /usr/src/unicorn-$UNICORNVER | |
RUN ./make.sh && ./make.sh install | |
# Build the Python bindings | |
WORKDIR /usr/src/unicorn-$UNICORNVER/bindings/python | |
RUN make install | |
########################################################### | |
## Install the Captsone Engine | |
# Get the Capstone-Engine sources | |
WORKDIR /usr/src | |
RUN wget https://github.com/aquynh/capstone/archive/$CAPSTONEVER.tar.gz && tar -xzf $CAPSTONEVER.tar.gz | |
# Build the Unicorn-Engine | |
WORKDIR /usr/src/capstone-$CAPSTONEVER | |
RUN ./make.sh && ./make.sh install | |
# Build the Python bindings | |
WORKDIR /usr/src/capstone-$CAPSTONEVER/bindings/python | |
RUN make install | |
########################################################### | |
## Install the Keystone Engine | |
# Get the Keystone-Engine sources | |
WORKDIR /usr/src | |
RUN wget https://github.com/keystone-engine/keystone/archive/$KEYSTONEVER.tar.gz && tar -xzf $KEYSTONEVER.tar.gz | |
# Build the Keystone-Engine | |
WORKDIR /usr/src/keystone-$KEYSTONEVER | |
RUN mkdir build | |
WORKDIR /usr/src/keystone-$KEYSTONEVER/build | |
RUN ../make-share.sh | |
RUN make install | |
# Build the Python bindings | |
WORKDIR /usr/src/keystone-$KEYSTONEVER/bindings/python | |
RUN make install | |
# Very important for Ubuntu! Otherwise keystone python scripts will not run | |
RUN sed -i '1i /usr/local/lib/' /etc/ld.so.conf | |
RUN ldconfig | |
########################################################### | |
# Cleanup | |
RUN rm -rf /usr/src/* | |
WORKDIR /root | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from capstone import * | |
from binascii import unhexlify | |
# Machine code x86 32-bit | |
CODE = unhexlify("414A") # => "\x41\x4A" | |
BASE_ADDRESS = 0x00400526 | |
def main(): | |
try: | |
# Initialize engine in X86 32-bit mode | |
cap = Cs(CS_ARCH_X86, CS_MODE_32) | |
for i in cap.disasm(CODE, BASE_ADDRESS): | |
print("0x%08x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str)) | |
except CsError as e: | |
print("ERROR: %s" %e) | |
if __name__ == "__main__": | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from keystone import * | |
from struct import pack | |
from binascii import hexlify | |
# Separate assembly instructions by ; or \n | |
CODE = "INC ECX\n" \ | |
"DEC EDX\n" | |
def main(): | |
try: | |
# Initialize engine in X86 32-bit mode | |
ks = Ks(KS_ARCH_X86, KS_MODE_32) | |
encoding, count = ks.asm(CODE) | |
machine_code = "" | |
for opcode in encoding: | |
machine_code += pack("B", opcode) | |
print("Machine Code:\n%s\n" %(hexlify(machine_code))) | |
except KsError as e: | |
print("ERROR: %s" %e) | |
if __name__ == "__main__": | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from unicorn import * | |
from unicorn.x86_const import * | |
from binascii import hexlify, unhexlify | |
X86_CODE32 = unhexlify("414A") | |
BASE_ADDRESS = 0x0040059d | |
def main(): | |
try: | |
emu = Uc(UC_ARCH_X86, UC_MODE_32) | |
emu.mem_map((BASE_ADDRESS/0x1000)*0x1000, 2 * 1024 * 1024) | |
emu.mem_write(BASE_ADDRESS, X86_CODE32) | |
emu.reg_write(UC_X86_REG_ECX, 0x9) | |
emu.reg_write(UC_X86_REG_EDX, 0x5) | |
emu.emu_start(BASE_ADDRESS, BASE_ADDRESS + len(X86_CODE32)) | |
print("Emulation done.") | |
print(">>> ECX = 0x%08x" % emu.reg_read(UC_X86_REG_ECX)) | |
print(">>> EDX = 0x%08x" % emu.reg_read(UC_X86_REG_EDX)) | |
except UcError as e: | |
print("ERROR: %s" % e) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment