Skip to content

Instantly share code, notes, and snippets.

@foxoman
Last active January 22, 2024 16:49
Show Gist options
  • Save foxoman/af83d383bc4fef267c3d25aa5f8f81ff to your computer and use it in GitHub Desktop.
Save foxoman/af83d383bc4fef267c3d25aa5f8f81ff to your computer and use it in GitHub Desktop.
Using native code/shellcode and assembly language with Nim
# ----------------------------------
# Shellcode Execution Utility in Nim
# ----------------------------------
# This Nim script is designed to execute a predefined shellcode,
# a small piece of low-level code used for various purposes.
# In this specific case, the shellcode is a function that performs
# hashing of a string.
#
# The script takes a hardcoded string "Fergo", loads the shellcode
# into memory, and then executes the shellcode using this string
# as the input. The shellcode function returns the hash of the
# input string as a 32-bit integer.
# The script then prints the hashed result in hexadecimal format.
#
# The shellcode loaded into memory using the VirtualAlloc function,
# which is a part of the Windows API. After the execution, the memory
# is freed using the VirtualFree function to prevent memory leaks.
#
# Please note:
# This script serves as an example of how to execute shellcode in Nim.
# Be aware that executing arbitrary shellcode can pose security risks.
#
# Author: Sultan Al Isaiee @foxoman
# Date: 11/07/2023
# Translation of C# Code: https://www.fergonez.net/post/shellcode-csharp
# We're using two modules: `winim` provides Windows API bindings, and
# `strformat` allows for Python-like string formatting.
import winim/lean
import strformat
# This is our shellcode. In computing, shellcode is a small piece
# of code used as the payload in the exploitation of a software
# vulnerability.
#[
section .text
global _start
_start:
mov edx, 0x811c9dc5
mov ebx, 0xf0b
mov esi, 0xc033c0be
xor edx, 0x93d069
mov eax, 0x10001
mov al, BYTE [ecx]
dec eax
inc ecx
dec eax
inc eax
dec eax
test al, al
jnz _start
mov eax, edx
ret
]#
# It's often written in machine code. Here it is represented as an array
# of bytes.
const shellcode: array[30, byte] = [
byte 0xBA, 0xC5, 0x9D, 0x1C, 0x81, 0xEB, 0x0B, 0x0F, 0xBE, 0xC0,
0x33, 0xC2, 0x69, 0xD0, 0x93, 0x01, 0x00, 0x01, 0x8A, 0x01, 0x48,
0xFF, 0xC1, 0x84, 0xC0, 0x75, 0xEC, 0x8B, 0xC2, 0xC3
]
# We allocate memory in our program to store the shellcode. `VirtualAlloc`
# is a Windows API function that reserves, commits, or changes the state
# of a region of pages in the virtual address space of the calling process
# (our program in this case).
let buffer = VirtualAlloc(NULL,
shellcode.len(),
MEM_COMMIT,
PAGE_EXECUTE_READWRITE)
# We check if memory allocation was successful.
# VirtualAlloc returns NULL when it fails to allocate memory.
# If that happens, we print an error message and exit the program.
if buffer == NULL:
quit("[Error] Unable to allocate memory for shellcode. The program will exit.")
# We copy the shellcode into the memory we just allocated.
copyMem(buffer, addr shellcode, shellcode.len())
# We prepare the string that we're going to pass to the shellcode function.
let stringArray = "Fergo\0" # For Safety will use Null Terminated String
# We declare a type for a function that takes a single cstring
# (a string in C language) argument and returns a uint32
# (32-bit unsigned integer).
type HashPrototype = proc(s: cstring): uint32 {.stdcall.}
# We cast the shellcode address to a HashPrototype function pointer.
# In simple terms, we're saying, "Treat the code in this memory
# address as a function that matches our HashPrototype type."
let MyHashingFunction = cast[HashPrototype](buffer)
# We call the shellcode function, passing it our string.
# It returns the result of hashing our string, according to the code
# in the shellcode.
let hashedResult = MyHashingFunction(stringArray.cstring)
# We print the result in hexadecimal form.
echo(fmt"[*] Here is hashed result in hex: {hashedResult:0X}")
# Finally, we free the memory we allocated earlier.
# This is good practice because it prevents memory leaks—situations
# where a program uses more and more memory over time, which can
# eventually cause the program to slow down or crash.
discard VirtualFree(buffer, 0, MEM_RELEASE)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment