int fun (void)
{
typedef void (pFun *)(char *); //这个是函数的申明
char code[1024]; //这里放接收回来的代码内容
char par[64]; //参数
getcode(code , par) ; //从网络接收到代码和参数
((pFun)code)(); //执行代码
//这里出错。。。。。。。。。。。。。。
......
}
懂的告诉我下,我刚怎么做才行。
谢谢了。
13 个解决方案
#1
@___@ 太强了
不过定义在栈上的是不行的,看看VirtualAlloc这个函数和它的MEM_EXECUTE这个权限。还有这个机器码局限很多啊,不能有大jump,也不能调用api,写的人一定很强,偶像。
不过定义在栈上的是不行的,看看VirtualAlloc这个函数和它的MEM_EXECUTE这个权限。还有这个机器码局限很多啊,不能有大jump,也不能调用api,写的人一定很强,偶像。
#2
有一系列问题需要解决:代码是32位还是64位的,是否特定于CPU(for intel or AMD),是完全重定位的还是需要一些初始化的?... 呵呵,是不是很麻烦呢?
其实也可以简单点, 假设客户端可以正确区分并正确请求相应的代码, 而代码用一个dll封装,那么程序的逻辑就可以简化成从服务器下载一个DLL文件并执行之,这样就可以思路清晰地实现楼主的要求了.(如果要求DLL直接从内存中加载也是可以的,google一下.)
其实也可以简单点, 假设客户端可以正确区分并正确请求相应的代码, 而代码用一个dll封装,那么程序的逻辑就可以简化成从服务器下载一个DLL文件并执行之,这样就可以思路清晰地实现楼主的要求了.(如果要求DLL直接从内存中加载也是可以的,google一下.)
#3
偶像。。关注下
#4
这个太强了。
这个太强了。
这个太强了。
#5
谢谢楼上两位指点,看来我还得仔细琢磨下了。
用库也行,就是怕太大了,很多个函数呢。
网络传输的时候太大不行,一个函数就好几百字节呢,用UDP的,拆包也麻烦。
用库也行,就是怕太大了,很多个函数呢。
网络传输的时候太大不行,一个函数就好几百字节呢,用UDP的,拆包也麻烦。
#6
初步考虑下,觉得原因如下:
我把代码拷贝到栈中,所以它的地址应该是SS:EBP,段寄存器是SS,而代码段寄存器是CS,地址应该是CS:EIP,
所以直接把SS:EBP强制转换为CS:EIP是不对的,这就要考虑重定位问题了,啊啊,太麻烦了,再去研究下怎么弄
吧,有结果了把这些东东全部帖上来,希望大家多多指点。
我把代码拷贝到栈中,所以它的地址应该是SS:EBP,段寄存器是SS,而代码段寄存器是CS,地址应该是CS:EIP,
所以直接把SS:EBP强制转换为CS:EIP是不对的,这就要考虑重定位问题了,啊啊,太麻烦了,再去研究下怎么弄
吧,有结果了把这些东东全部帖上来,希望大家多多指点。
#7
哈哈,弄出来了。
一般情况下,CS是可读可执行不可写、SS是可读可写可执行、DS是可读可写不可执行。
为了防止栈溢出、操作系统会禁止对SS的执行,64位机已经在硬件上做了这个工作;32位机上要在栈上执行代码
只要用VirtualAlloc这个函数分配一段内存,打上可执行标记即可(superarhow老兄说的对啊),64位机没试过。
平常没玩过远程注入啊,其实这个技术已经很成熟了,刚看到别人的例子了。
伪代码如下:
UINT fun (LPVOID m_lpPar)
{
::MessageBox(NULL , "垃圾目标,封我号,扣我装备,我Cao你NN。" , "提示" , 0);
return 0;
}
void test(void)
{
typedef UINT (*pfun)(LPVOID);
unsigned char * p = (unsigned char *)fun;
int i = 0 ;
while(p[i++] != 0xc3); //计算函数的长度。
LPVOID m_lpThread = VirtualAlloc(NULL , i , MEM_RESERVE | MEM_COMMIT , PAGE_EXECUTE_READWRITE); //打上可执行标记、可读写
DWORD m_dwNum = 0; //函数的内容写进去
WriteProcessMemory(GetCurrentProcess() , m_lpThread , p , i , &m_dwNum );
AfxBeginThread((AFX_THREADPROC)m_lpThread, NULL , 0 , 0 , 0 , NULL);
...... //OK了,不过只能在发行状态运行哦。
VirtualFree(m_lpThread, i , MEM_DECOMMIT | MEM_RELEASE);
......
}
一般情况下,CS是可读可执行不可写、SS是可读可写可执行、DS是可读可写不可执行。
为了防止栈溢出、操作系统会禁止对SS的执行,64位机已经在硬件上做了这个工作;32位机上要在栈上执行代码
只要用VirtualAlloc这个函数分配一段内存,打上可执行标记即可(superarhow老兄说的对啊),64位机没试过。
平常没玩过远程注入啊,其实这个技术已经很成熟了,刚看到别人的例子了。
伪代码如下:
UINT fun (LPVOID m_lpPar)
{
::MessageBox(NULL , "垃圾目标,封我号,扣我装备,我Cao你NN。" , "提示" , 0);
return 0;
}
void test(void)
{
typedef UINT (*pfun)(LPVOID);
unsigned char * p = (unsigned char *)fun;
int i = 0 ;
while(p[i++] != 0xc3); //计算函数的长度。
LPVOID m_lpThread = VirtualAlloc(NULL , i , MEM_RESERVE | MEM_COMMIT , PAGE_EXECUTE_READWRITE); //打上可执行标记、可读写
DWORD m_dwNum = 0; //函数的内容写进去
WriteProcessMemory(GetCurrentProcess() , m_lpThread , p , i , &m_dwNum );
AfxBeginThread((AFX_THREADPROC)m_lpThread, NULL , 0 , 0 , 0 , NULL);
...... //OK了,不过只能在发行状态运行哦。
VirtualFree(m_lpThread, i , MEM_DECOMMIT | MEM_RELEASE);
......
}
#8
我保证,你接收到的代码,这样100%用不起
"垃圾目标,封我号,扣我装备,我Cao你NN。"
"提示"
在目标进程,这两个字符串 绝对是未定义的
函数 MessageBoxA 也不能保证地址一致
"垃圾目标,封我号,扣我装备,我Cao你NN。"
"提示"
在目标进程,这两个字符串 绝对是未定义的
函数 MessageBoxA 也不能保证地址一致
#9
能说明原因吗?
你试过了吗?
如果你没试过,你就不要臆断哦,会误导人的。
可惜这里不能发图,要不我就把运行的过程发上来。
另:
直接调用效果一样,((pfun)m_lpThread)(NULL);
你试过了吗?
如果你没试过,你就不要臆断哦,会误导人的。
可惜这里不能发图,要不我就把运行的过程发上来。
另:
直接调用效果一样,((pfun)m_lpThread)(NULL);
#10
我看错了,老兄。哈哈
发过来的机器码中没有API调用,这个是本地的。
用API和静态数据是会出错。
发过来的机器码中没有API调用,这个是本地的。
用API和静态数据是会出错。
#11
我不骗你,你的目的说得很明确,是从网络接受到的代码片断。
代码里面,那两个字符串并不是保存在这段代码里面的.
如果真要做的话,建议:
1. 保证远程系统和目标系统一致,或者你自己提供一个DLL来wrap LoadLibrayA 和 GetProcAddress 函数
2. 字符串和函数地址请放在一个结构里面
3. 调用的时候,把这个结构的地址传给 thread.
看代码:
那个DLL就比较简单,直接把 GetProcAddress 和 LoadLibrary 包装一次,可以保证本地和远程的两个函数在内存中的地址一致.
UINT fun (LPVOID m_lpPar)
{
::MessageBox(NULL , "垃圾目标,封我号,扣我装备,我Cao你NN。" , "提示" , 0);
return 0;
}
代码里面,那两个字符串并不是保存在这段代码里面的.
如果真要做的话,建议:
1. 保证远程系统和目标系统一致,或者你自己提供一个DLL来wrap LoadLibrayA 和 GetProcAddress 函数
2. 字符串和函数地址请放在一个结构里面
3. 调用的时候,把这个结构的地址传给 thread.
看代码:
////////////////////////////////////////////////////////////////////////////
// 远程代码片断
typedef HINSTANCE (WINAPI * MYLOADLIBRARYPROC)(char*);
typedef HINSTANCE (WINAPI * MYGETPROCADDRESSPROC)(HINSTANCE, char*);
typedef HINSTANCE (WINAPI * MSGBOXPROC)(HWND, char*, char*, UINT);
struct tagREMOTEPARAM
{
MYLOADLIBRARYPROC pMyLoadLibrary;
MYGETPROCADDRESSPROC pMyGetProcAddress;
char szUser32[MAX_PATH];
char szMsgBoxA[64];
char szMsg[200];
char szTitle[100];
} REMOTEPARAM;
DWORD WINAPI MyThread(LPVOID pParam)
{
REMOTEPARAM *pParam = reinterpret_cast<REMOTEPARAM*>(pParam);
HINSTANCE hUser32 = pParam->pMyLoadLibrary(pParam->szUser32);
MSGBOXPROC pMsgBox = reinterpret_cast<MSGBOXPROC>(pParam->pMyGetProcAddress(hUser32, pParam->szMsgBoxA));
pMsgBox(NULL, pParam->szMsg, pParam->szTitle, MB_OK);
return 0;
}
void FillParam(REMOTEPARAM *pParam)
{
if(!pParam) return;
HINSTANCE hLib = LoadLibrary("MYWRAP.DLL");
pParam->pMyLoadLibrary = reinterpret_cast<MYLOADLIBRARYPROC>(GetProcAddress(hLib, "MyLoadLibrary"));
pParam->pMyGetProcAddress = reinterpret_cast<MYGETPROCADDRESSPROC>(GetProcAddress(hLib, "MyGetProcAddress"));
lstrcpy(pParam->szUser32, "User32.dll");
lstrcpy(pParam->szMsgBoxA, "MessageBoxA");
lstrcpy(pParam->szMsg, "This is the message text!");
lstrcpy(pParam->szTitle, "Title");
}
////////////////////////////////////////////////////////////////////////////
// 本地代码片断
void Dummy()
{
LPVOID pParamBuff;
LPVOID pCodeBuff;
DWORD dwID;
LoadLibrary("MYWRAP.DLL"); // 确保这个DLL已载入
pParamBuff = VirtualAlloc(...); // 为数据分配空间
pCodeBuff = VirtualAlloc(...); // 为代码分配空间, 要有 PAGE_EXECUTE_READWRITE 属性
// pReceivedParam 为接收到的数据, nParam 为数据长度
// pReceivedCode 为收到的代码, nCode 为代码长度
memcpy(pParamBuff, pReceivedParam, nParam);
memcpy(pCodeBuff, pReceivedCode, nCode);
CreateThread(NULL, NULL, reinterpret_cast<LPTHREAD_START_ROUTINE>(pCodeBuff), pParamBuff, NULL, &dwID);
}
那个DLL就比较简单,直接把 GetProcAddress 和 LoadLibrary 包装一次,可以保证本地和远程的两个函数在内存中的地址一致.
#12
打字真累啊,hehe
#13
老兄厉害,谢谢指教。
分加你了。
分加你了。
#1
@___@ 太强了
不过定义在栈上的是不行的,看看VirtualAlloc这个函数和它的MEM_EXECUTE这个权限。还有这个机器码局限很多啊,不能有大jump,也不能调用api,写的人一定很强,偶像。
不过定义在栈上的是不行的,看看VirtualAlloc这个函数和它的MEM_EXECUTE这个权限。还有这个机器码局限很多啊,不能有大jump,也不能调用api,写的人一定很强,偶像。
#2
有一系列问题需要解决:代码是32位还是64位的,是否特定于CPU(for intel or AMD),是完全重定位的还是需要一些初始化的?... 呵呵,是不是很麻烦呢?
其实也可以简单点, 假设客户端可以正确区分并正确请求相应的代码, 而代码用一个dll封装,那么程序的逻辑就可以简化成从服务器下载一个DLL文件并执行之,这样就可以思路清晰地实现楼主的要求了.(如果要求DLL直接从内存中加载也是可以的,google一下.)
其实也可以简单点, 假设客户端可以正确区分并正确请求相应的代码, 而代码用一个dll封装,那么程序的逻辑就可以简化成从服务器下载一个DLL文件并执行之,这样就可以思路清晰地实现楼主的要求了.(如果要求DLL直接从内存中加载也是可以的,google一下.)
#3
偶像。。关注下
#4
这个太强了。
这个太强了。
这个太强了。
#5
谢谢楼上两位指点,看来我还得仔细琢磨下了。
用库也行,就是怕太大了,很多个函数呢。
网络传输的时候太大不行,一个函数就好几百字节呢,用UDP的,拆包也麻烦。
用库也行,就是怕太大了,很多个函数呢。
网络传输的时候太大不行,一个函数就好几百字节呢,用UDP的,拆包也麻烦。
#6
初步考虑下,觉得原因如下:
我把代码拷贝到栈中,所以它的地址应该是SS:EBP,段寄存器是SS,而代码段寄存器是CS,地址应该是CS:EIP,
所以直接把SS:EBP强制转换为CS:EIP是不对的,这就要考虑重定位问题了,啊啊,太麻烦了,再去研究下怎么弄
吧,有结果了把这些东东全部帖上来,希望大家多多指点。
我把代码拷贝到栈中,所以它的地址应该是SS:EBP,段寄存器是SS,而代码段寄存器是CS,地址应该是CS:EIP,
所以直接把SS:EBP强制转换为CS:EIP是不对的,这就要考虑重定位问题了,啊啊,太麻烦了,再去研究下怎么弄
吧,有结果了把这些东东全部帖上来,希望大家多多指点。
#7
哈哈,弄出来了。
一般情况下,CS是可读可执行不可写、SS是可读可写可执行、DS是可读可写不可执行。
为了防止栈溢出、操作系统会禁止对SS的执行,64位机已经在硬件上做了这个工作;32位机上要在栈上执行代码
只要用VirtualAlloc这个函数分配一段内存,打上可执行标记即可(superarhow老兄说的对啊),64位机没试过。
平常没玩过远程注入啊,其实这个技术已经很成熟了,刚看到别人的例子了。
伪代码如下:
UINT fun (LPVOID m_lpPar)
{
::MessageBox(NULL , "垃圾目标,封我号,扣我装备,我Cao你NN。" , "提示" , 0);
return 0;
}
void test(void)
{
typedef UINT (*pfun)(LPVOID);
unsigned char * p = (unsigned char *)fun;
int i = 0 ;
while(p[i++] != 0xc3); //计算函数的长度。
LPVOID m_lpThread = VirtualAlloc(NULL , i , MEM_RESERVE | MEM_COMMIT , PAGE_EXECUTE_READWRITE); //打上可执行标记、可读写
DWORD m_dwNum = 0; //函数的内容写进去
WriteProcessMemory(GetCurrentProcess() , m_lpThread , p , i , &m_dwNum );
AfxBeginThread((AFX_THREADPROC)m_lpThread, NULL , 0 , 0 , 0 , NULL);
...... //OK了,不过只能在发行状态运行哦。
VirtualFree(m_lpThread, i , MEM_DECOMMIT | MEM_RELEASE);
......
}
一般情况下,CS是可读可执行不可写、SS是可读可写可执行、DS是可读可写不可执行。
为了防止栈溢出、操作系统会禁止对SS的执行,64位机已经在硬件上做了这个工作;32位机上要在栈上执行代码
只要用VirtualAlloc这个函数分配一段内存,打上可执行标记即可(superarhow老兄说的对啊),64位机没试过。
平常没玩过远程注入啊,其实这个技术已经很成熟了,刚看到别人的例子了。
伪代码如下:
UINT fun (LPVOID m_lpPar)
{
::MessageBox(NULL , "垃圾目标,封我号,扣我装备,我Cao你NN。" , "提示" , 0);
return 0;
}
void test(void)
{
typedef UINT (*pfun)(LPVOID);
unsigned char * p = (unsigned char *)fun;
int i = 0 ;
while(p[i++] != 0xc3); //计算函数的长度。
LPVOID m_lpThread = VirtualAlloc(NULL , i , MEM_RESERVE | MEM_COMMIT , PAGE_EXECUTE_READWRITE); //打上可执行标记、可读写
DWORD m_dwNum = 0; //函数的内容写进去
WriteProcessMemory(GetCurrentProcess() , m_lpThread , p , i , &m_dwNum );
AfxBeginThread((AFX_THREADPROC)m_lpThread, NULL , 0 , 0 , 0 , NULL);
...... //OK了,不过只能在发行状态运行哦。
VirtualFree(m_lpThread, i , MEM_DECOMMIT | MEM_RELEASE);
......
}
#8
我保证,你接收到的代码,这样100%用不起
"垃圾目标,封我号,扣我装备,我Cao你NN。"
"提示"
在目标进程,这两个字符串 绝对是未定义的
函数 MessageBoxA 也不能保证地址一致
"垃圾目标,封我号,扣我装备,我Cao你NN。"
"提示"
在目标进程,这两个字符串 绝对是未定义的
函数 MessageBoxA 也不能保证地址一致
#9
能说明原因吗?
你试过了吗?
如果你没试过,你就不要臆断哦,会误导人的。
可惜这里不能发图,要不我就把运行的过程发上来。
另:
直接调用效果一样,((pfun)m_lpThread)(NULL);
你试过了吗?
如果你没试过,你就不要臆断哦,会误导人的。
可惜这里不能发图,要不我就把运行的过程发上来。
另:
直接调用效果一样,((pfun)m_lpThread)(NULL);
#10
我看错了,老兄。哈哈
发过来的机器码中没有API调用,这个是本地的。
用API和静态数据是会出错。
发过来的机器码中没有API调用,这个是本地的。
用API和静态数据是会出错。
#11
我不骗你,你的目的说得很明确,是从网络接受到的代码片断。
代码里面,那两个字符串并不是保存在这段代码里面的.
如果真要做的话,建议:
1. 保证远程系统和目标系统一致,或者你自己提供一个DLL来wrap LoadLibrayA 和 GetProcAddress 函数
2. 字符串和函数地址请放在一个结构里面
3. 调用的时候,把这个结构的地址传给 thread.
看代码:
那个DLL就比较简单,直接把 GetProcAddress 和 LoadLibrary 包装一次,可以保证本地和远程的两个函数在内存中的地址一致.
UINT fun (LPVOID m_lpPar)
{
::MessageBox(NULL , "垃圾目标,封我号,扣我装备,我Cao你NN。" , "提示" , 0);
return 0;
}
代码里面,那两个字符串并不是保存在这段代码里面的.
如果真要做的话,建议:
1. 保证远程系统和目标系统一致,或者你自己提供一个DLL来wrap LoadLibrayA 和 GetProcAddress 函数
2. 字符串和函数地址请放在一个结构里面
3. 调用的时候,把这个结构的地址传给 thread.
看代码:
////////////////////////////////////////////////////////////////////////////
// 远程代码片断
typedef HINSTANCE (WINAPI * MYLOADLIBRARYPROC)(char*);
typedef HINSTANCE (WINAPI * MYGETPROCADDRESSPROC)(HINSTANCE, char*);
typedef HINSTANCE (WINAPI * MSGBOXPROC)(HWND, char*, char*, UINT);
struct tagREMOTEPARAM
{
MYLOADLIBRARYPROC pMyLoadLibrary;
MYGETPROCADDRESSPROC pMyGetProcAddress;
char szUser32[MAX_PATH];
char szMsgBoxA[64];
char szMsg[200];
char szTitle[100];
} REMOTEPARAM;
DWORD WINAPI MyThread(LPVOID pParam)
{
REMOTEPARAM *pParam = reinterpret_cast<REMOTEPARAM*>(pParam);
HINSTANCE hUser32 = pParam->pMyLoadLibrary(pParam->szUser32);
MSGBOXPROC pMsgBox = reinterpret_cast<MSGBOXPROC>(pParam->pMyGetProcAddress(hUser32, pParam->szMsgBoxA));
pMsgBox(NULL, pParam->szMsg, pParam->szTitle, MB_OK);
return 0;
}
void FillParam(REMOTEPARAM *pParam)
{
if(!pParam) return;
HINSTANCE hLib = LoadLibrary("MYWRAP.DLL");
pParam->pMyLoadLibrary = reinterpret_cast<MYLOADLIBRARYPROC>(GetProcAddress(hLib, "MyLoadLibrary"));
pParam->pMyGetProcAddress = reinterpret_cast<MYGETPROCADDRESSPROC>(GetProcAddress(hLib, "MyGetProcAddress"));
lstrcpy(pParam->szUser32, "User32.dll");
lstrcpy(pParam->szMsgBoxA, "MessageBoxA");
lstrcpy(pParam->szMsg, "This is the message text!");
lstrcpy(pParam->szTitle, "Title");
}
////////////////////////////////////////////////////////////////////////////
// 本地代码片断
void Dummy()
{
LPVOID pParamBuff;
LPVOID pCodeBuff;
DWORD dwID;
LoadLibrary("MYWRAP.DLL"); // 确保这个DLL已载入
pParamBuff = VirtualAlloc(...); // 为数据分配空间
pCodeBuff = VirtualAlloc(...); // 为代码分配空间, 要有 PAGE_EXECUTE_READWRITE 属性
// pReceivedParam 为接收到的数据, nParam 为数据长度
// pReceivedCode 为收到的代码, nCode 为代码长度
memcpy(pParamBuff, pReceivedParam, nParam);
memcpy(pCodeBuff, pReceivedCode, nCode);
CreateThread(NULL, NULL, reinterpret_cast<LPTHREAD_START_ROUTINE>(pCodeBuff), pParamBuff, NULL, &dwID);
}
那个DLL就比较简单,直接把 GetProcAddress 和 LoadLibrary 包装一次,可以保证本地和远程的两个函数在内存中的地址一致.
#12
打字真累啊,hehe
#13
老兄厉害,谢谢指教。
分加你了。
分加你了。