远程线程注入(先简单说,下面会详细说)
今天整理下代码注入(远程线程注入),所谓代码注入,可以简单的理解为是在指定内进程里申请一块内存,然后把我们自己的执行代码和一些变量拷贝进去(通常是以启线程的方式),然后直接调用对方内存里我们拷贝进去的那部分代码(创建一个线程)。这样就行了,此时我们的这个线程就是目标进程的子线程了。但是要注意一点,代码注入之所以能成功重点是:有些系统常用的dll里的某些函数,在不同的进程里面获取到的地址是一样的(此处注意,一样的概念是指数值一样,但是这个数值存的地方不一样。也就是A里面的b变量的值等于C里面的d变量的值。这个要清楚,不然在学习API劫持的时候可能会迷茫)。
这两个函数,一个是加载dll库,一个是从已经加载的库句柄里拿出来某个函数的地址,可以理解成是把一个dll加到内存里,然后获取里面某个函数的地址,得到这个地址后就可以直接调用了,这两个简单的函数经常用到,无论是常规调用还是静态免杀都经常用。
2.OpenProcess()
根据进程id获取进程的句柄,也就是获取进程操控权。
3.VirtualAllocEx()
在指定进程里开辟一块内存,用于存放自己的代码和参数。
4.WriteProcessMemory()
3里面的函数会在一个进程里开辟一块内存,然后在那个内存里直接用本函数4进行数据写入,就是在别人那开一块内存然后写自己的东西。
5.CreateRemoteThread()
最核心的函数,在指定进程的某个内存位置存储的函数为线程函数,启动一个线程,当然被启动的这个线程属于指定的这个进程。
OK上面那5个API就是代码注入需要的几个基本的了,接下来我说一下我对线程注入的理解:
今天整理下代码注入(远程线程注入),所谓代码注入,可以简单的理解为是在指定内进程里申请一块内存,然后把我们自己的执行代码和一些变量拷贝进去(通常是以启线程的方式),然后直接调用对方内存里我们拷贝进去的那部分代码(创建一个线程)。这样就行了,此时我们的这个线程就是目标进程的子线程了。但是要注意一点,代码注入之所以能成功重点是:有些系统常用的dll里的某些函数,在不同的进程里面获取到的地址是一样的(此处注意,一样的概念是指数值一样,但是这个数值存的地方不一样。也就是A里面的b变量的值等于C里面的d变量的值。这个要清楚,不然在学习API劫持的时候可能会迷茫)。
首先先介绍几个需要的API
1.LoadLibrary() 和 GetProcAddress()这两个函数,一个是加载dll库,一个是从已经加载的库句柄里拿出来某个函数的地址,可以理解成是把一个dll加到内存里,然后获取里面某个函数的地址,得到这个地址后就可以直接调用了,这两个简单的函数经常用到,无论是常规调用还是静态免杀都经常用。
2.OpenProcess()
根据进程id获取进程的句柄,也就是获取进程操控权。
3.VirtualAllocEx()
在指定进程里开辟一块内存,用于存放自己的代码和参数。
4.WriteProcessMemory()
3里面的函数会在一个进程里开辟一块内存,然后在那个内存里直接用本函数4进行数据写入,就是在别人那开一块内存然后写自己的东西。
5.CreateRemoteThread()
最核心的函数,在指定进程的某个内存位置存储的函数为线程函数,启动一个线程,当然被启动的这个线程属于指定的这个进程。
OK上面那5个API就是代码注入需要的几个基本的了,接下来我说一下我对线程注入的理解:
线程注入其实很好理解,就是说我们通过一定的手段在宿主也就是需要被注入的进程那获取权限,得到权限之后我们要在这个进程上开辟一定的内存,然后把自己的线程函数内容以及参数什么的全都拷贝过去,这样目标进程上有我们的函数,我们的参数,我们这个时候只是需要"帮"它启动一下这个线程就OK了,直接用CreateRemoteThread函数在对方进程的某个内存位置的某个线程函数作为线程函数启动。
然后上面的那个解释是宏观的,也就是泛泛而谈,最最核心的思路是这样:对于每个进程,他们调用的API大多都是自己随时调用随时获取的,地址也不一样,但是只有极少数的几个系统核心dll他们不一样,系统为了优化和统一管理,使得每个人load的dll然后从里面获取的函数地址是一样的,也就是大家共用一套已经被载入的dll地址,可以用的也是用的最多的就是User32.dll,kernel32.dll(我目前就知道这两个,但是不重要只要知道一个kernel32.dll然后在里面做一个