Offensive Nim - Cheatsheet
Using Nim Offensively
The following things are useful snippets for programming in offensive Nim.
- [[#Compilation)
- [[#Dividing Functionality)
- [[#Define Shellcode as sequence)
- [[#Get direct address to a seq)
- [[#Casting Windows Types)
- [[#Instantiating Windows Structs)
- [[#Create Windows Structs from Addr)
- [[#Formatting)
Compilation
Taken from the Nim FAQ: https://nim-lang.org/faq.html
For the standard configuration file,
-d:danger -d:strip --opt:size
does the trick. If supported by your compiler, you can also enable link-time optimization the same way as described in the previous answer.
Dividing Functionality
The when
keyword can be used as compile-time if
.
When compiling: nim.exe -d:finalimplant
And can be used in the code:
|
|
This is perfect for having several different injections and other stuff in a library and only compile a certain subset of those
Often used Code References
Define Shellcode as sequence
The benefit of using seq
instead of an array is that the size is dynamic and can be easily loaded from a file/network:
let shellcode: seq[byte] = @[byte 0x41, 0x41, 0x41]
Get direct address to a seq
It is not possible to use the addr
keyword to get a
direct address of a seq[byte]
, hower the unsafeAddr
can be used, when indexing the sequence:
|
|
Info: It is important to index the variable (shellcode[0]
)
Casting Windows Types
Most Windows types can be casted quite easily:
|
|
Instantiating Windows Structs
Structs/Typedefs are objects
in nim and defined like that:
|
|
There are two ways of intantiating such objects:
- Full
|
|
It seems that for initialized objects, it is neccessary to pass the object with the unsafeAddr
keyword as the addr
isn’t working (does this make sense?)
- Partially/Empty
The benefit is that its shorter to declare, and the keyword addr
can be used
|
|
Dereferencing structs from a pointer
- To instantiate a Windows struct (e.g. DOS_HEADER) from an address:
|
|
- This works for aprsing bytes from a byte sequence:
|
|
Calculating with Windows Types
- PVOID (something weird)
- Cast to int (or uint64) when dealing with addresses
- Int seems to represent the length of the compiled binary
Formatting
- Outputing large integers as hex:
|
|
Reading Strings
In C its trivial to read a char *
from an address as its nothing else but raw bytes in memory.
In Nim however, a function is required to actually read the bytes from memory into a string.
|
|
Some Windows API structs contain arrays of WCHAR
or CHAR
. To obtain a Nim string from those, the following snippet can be used:
|
|