① 如何用c语言对文件进行加密和解密急求......................
文件分为文本文件和二进制文件。加密方法也略有不同。
1、文本文件
加密的主要是文本的内容,最简单的方法就是修改文档的内容,比如1.txt中的文件内容:
abcd
只要给每一个字符+1,就可以实现加密。文件内容即会变为
bcde
2、二进制文件加密
二进制文件加密也就是对应用程序加密,需要理解可执行文件格式,比如Windows平台的Exe文件它是PE结构,Linux上的可执行文件是ELF结构,要对这样的程序进行加密,实际上是开发一种叫做“壳”的程序,这种程序的开发,需要将扎实的底层基础,同时也需要对软件加密解密有细致的理解,比如流行的vmprotect、z壳以及早些年的upx壳、aspack等等。
3、无论哪种加密都牵涉到文件操作的问题,使用C语言进行文件操作时,极少使用C标准库中的I/O函数,大多数使用操作系统提供的内存文件映射相关的API函数,有兴趣,可以搜索相关的资料。
② c语言 模块化编程 MAIN.C(28): error C141: syntax error near 'void'
你把main(void)中的那个void删了试试,学过很久了,软件也卸了,没办法帮你运行,但是我记得C语言中不支持这样的写法,你试试看。如果不对再帮你解答。
③ C语言中Cannot open include file: 'R.h': No such file or directory怎么解决 以及PROTECT()有什么作用
你引用了R.h库函数,而你电脑没有这个库函数,你可以删掉试一下
④ c语言中 #include<windos.h>文件头除了能限制机器输出时间,还有什么用途
是windows.h吧。这个头文件里有好多函数。你确定你都想知道么。
下面就是啦:
有关进程系统权限类
1:函数OpenProcessToken(
HANDLE ProcessHandle,//进程的句柄
DWORD DesiredAccess,//对进程的访问描述
PHANDLE TokenHandle//打开进程令牌的句柄指针
);
这个函数的作用是打开进程令牌
2: 函数LookupPrivilegeValue(
LPCTSTR lpSytemName,//系统名称
LPCTSTR lpName,//特权名称
PLUID lpluid//本地系统唯一的ID号
)
这个函数将返回一个本地系统内独一无二的ID,来用于系统权限的更改,它的第一个参数是系统名,nil表示本系统。第2个参数是特权的名字。第3个参数用来接收函数返回的ID。
3.函数AdjustTokenPrivileges(
HANDLE TokenHandle, //更改权限的令牌环句柄
BOOL DisableAllPrivileges, //是否修改所有权限的标志位
PTOKEN_PRIVILEGES NewState, //新的系统权限信息
DWORD BufferLength, //上一个参数的长度
PTOKEN_PRIVILEGES PreviousState, // 返回更改系统特权以前的权限
PDWORD ReturnLength //上一个参数的长度
);
这个函数用于更改进程的系统权限 ,第1个参数是要更改权限的令牌环句柄。第2个参数如果为true表示更改所有的系统权限 ,false表示更改部分。第3个参数是要更改的系统特权的值。第4个参数是第3个参数的大小。第5个参数返回更改系统特权以前的权限,我们不需要就设为nil。第6个参数是第5个参数的大小。
OpenProcess(
DWORD dwDesiredAccess,//访问标志
BOOL bInheritHandle,//继承句柄标志
DWORD dwProcessId //进程Id
)
这个函数用于修改我们宿主进程的一些属性,这些属性放在第一个参数里面比如说PROCESS_VM_OPEARTION就是允许远程VM操作,即允许VirtualProtectEx和WriteProcessMemory函数操作本进程内存空间。PROCESS_VM_WRITE就是允许远程VM写,即允许WriteProcessMemory函数访问本进程的内存空间。第二个参数是一个标志参数,用来确定返回的句柄是否可以被新的进程继承。我们的程序中设为False。第三个参数需要操作的进程Id,也就是我们的宿主进程的ID。
2:函数VirtualAllocEx(
HANDLE hProcess,//要进行操作的进程句柄,当然是我们的宿主了
LPVOID lpAddress,//分配空间的开始地址
DWORD dwSize,//分配空间的大小
DWORD flAllocationType,//分配空间的类型
DWOrd flProtect//访问保护类型
)
我们使用VirtualAllocEx函数在宿主进程中开辟一块内存空间,用于存放dll的文件名,VirtualAllocEx的第一参数是要操作的进程,第二个是开始地址,第三个是长度,第4,5个是操作参数。其中MEM_COMMIT表示本函数分配的物理内存或者是内存的页面文件,PAGE_READWRITE表示分配的区域内允许读写
函数WriteProcessMemory(
HANDLE hProcess,//所要操作的线程的句柄
LPVOID lpBaseAddress,//开始进行操作的起始地址
LPVOID lpBuffer,//所要写入的Bytes数
LPDWORD lpNuberofBytersWriteen//世纪写入的Bytes数
) 前面的函数在宿主内存中创建号空间后,现在往里面写入dll的名称,而我们的WriteProcessMemory函数就可以胜任这一项工作,WriteProcessMemory函数的第一个参数是需要往内存里面写入dd的进程句柄,第二个参数是 “要进行写操作”的目标内存起始地址,第三个参数是 “需要被写入的数据”的地址,第四个参数是准备要写入的长度,第五个参数是实际操作中写的长度,这个参数是被函数输出的。到这里我们就已经能成功把dll的路径名称写进了宿主的内存空间。
GetProcAddress(
HMODULE hMole, //dll模块的句柄
LPCSTR lpProcName // 函数名称
);
我们用这个函数主要想得到kernel32.dll中的函数LoadLibraryW的入口地址,所以
GetProcAddress(GetMoleHandle('Kernel32'), 'LoadLibraryW')就可以了,当然有些细节得符合程序编译器的要求,VC下使用就要改成
GetProcAddress(GetMoleHandle(TEXT("Kernel32")), "LoadLibraryW")的形式。
CreateRemoteThread (
HANDLE hProcess, //要进行操作的进程句柄,也就是我们的宿主句柄
LPSECURITY_ATTRIBUTES lpThreadAttributes, //线程安全属性的指针
DWORD dwStackSize, //初始化堆(stack)的大小
LPTHREAD_START_ROUTINE lpStartAddress,//新建线程函数的指针,或叫做地址
LPVOID lpParameter, //新建线程函数的参数
DWORD dwCreationFlags, //标志位
LPDWORD lpThreadId //线程返回值
);
这个函数就是本文的点睛之笔了,我们之前所做所有的一切,都是在为它做准备工作,它的功能就是在其他任何进程中创建新的线程,让其他的程序或进程附加执行我们的代码。
CreateRemoteThread函数的第一个参数是要操作的宿主进程句柄;第二个参数为线程安全参数的指针,这里设为nil;第三个参数为初始化堆(stack)的大小,这里设0;第四个参数为新建线程函数的指针或叫做地址或叫入口;第五个参数为新建线程函数的参数,这里就是我们的dll路径名称;第六个参数是标志位,这里设0;第七个参数是线程返回值。
⑤ c语言中的继承用什么关键字
在C语言中,不存在继承的概念。
继承是面向对象语言的概念,而C语言是面向过程的语言。
C++是在C语言基础上发展出的面向对象语言,其中的类可以继承。
在C++的继承中,区分继承类型,有三种关键字可以使用:
1 公有继承,使用关键字public;
2 私有继承,使用关键字private;
3 保护继承,使用关键字protect。
⑥ 免杀的方法
一.入口点加1免杀法:
1.用到工具PEditor
2.特点:非常简单实用,但有时还会被卡巴查杀]
3.操作要点:用PEditor打开无壳木马程序,把原入口点加1即可
【二.变化入口地址免杀法:】
1.用到工具:OllyDbg,PEditor
2.特点:操作也比较容易,而且免杀效果比入口点加1点要佳.
3.操作要点:用OD载入无壳的木马程序,把入口点的前二句移到零区域去执行,然后
又跳回到入口点的下面第三句继续执行.最后用PEditor把入口点改成零区域的地址
【三.加花指令法免杀法:】
1.用到工具:OllyDbg,PEditor
2.特点:免杀通用性非常好,加了花指令后,就基本达到大量杀毒软件的免杀.
3.操作要点:用OD打开无壳的木马程序,找到零区域,把我们准备好的花指令填进去
填好后又跳回到入口点,保存好后,再用PEditor把入口点改成零区域处填入花指令的着地址.
【四.加壳或加伪装壳免杀法:】
1.用到工具:一些冷门壳,或加伪装壳的工具,比如木马彩衣等.
2.特点:操作简单化,但免杀的时间不长,可能很快被杀,也很难躲过卡巴的追杀
3.操作要点:为了达到更好的免杀效果可采用多重加壳,或加了壳后在加伪装壳的免杀效果更佳
【五.打乱壳的头文件或壳中加花免杀法:】
1.用到工具:秘密行动 ,UPX加壳工具.
2.特点:操作也是傻瓜化,免杀效果也正当不错,特别对卡巴的免杀效果非常好
3.操作要点:首先一定要把没加过壳的木马程序用UPX加层壳,然后用秘密行动这款
工具中的SCramble功能进行把UPX壳的头文件打乱,从而达到免杀效果.
【六.修改文件特征码免杀法:】
1.用到工具:特征码定位器,OllyDbg
2.特点:操作较复杂,要定位修改一系列过程,而且只针对每种杀毒软件的免杀,要达
到多种杀毒软件的免杀,必需修改各种杀毒软件的特征码.但免杀效果好
[特征码修改方法]
特征码修改包括文件特征码修改和内存特征码修改,因为这二种特征码的修改方
法是通用的。所以就对目前流行的特征码修改方法作个总节。
[方法一:直接修改特征码的十六进制法]
1.修改方法:把特征码所对应的十六进制改成数字差1或差不多的十六进制.
2.适用范围:一定要精确定位特征码所对应的十六进制,修改后一定要测试一下能否正常使用.
[方法二:修改字符串大小写法]
1.修改方法:把特征码所对应的内容是字符串的,只要把大小字互换一下就可以了.
2.适用范围:特征码所对应的内容必需是字符串,否则不能成功.
[方法三:等价替换法]
1.修改方法:把特征码所对应的汇编指令命令中替换成功能类拟的指令.
2.适用范围:特征码中必需有可以替换的汇编指令.比如JN,JNE 换成JMP等.如果和我一样对汇编不懂的可以去查查8080汇编手册.
[方法四:指令顺序调换法]
1.修改方法:把具有特征码的代码顺序互换一下.
2.适用范围:具有一定的局限性,代码互换后要不能影响程序的正常执行
[方法五:通用跳转法]
1.修改方法:把特征码移到零区域(指代码的空隙处),然后一个JMP又跳回来执行.
2.适用范围:没有什么条件,是通用的改法,强烈建议大家要掌握这种改法.
木马免杀的综合修改方法
文件免杀方法:1.加冷门壳 2.加花指令 3.改程序入口点 4.改木马文件特征码的5种常用方法
5.还有其它的几种免杀修改技巧
【七.内存免杀方法:】
修改内存特征码:
方法1>直接修改特征码的十六进制法
方法2>修改字符串大小写法
方法3>等价替换法
方法4>指令顺序调换法
方法5>通用跳转法
壳入口修改法
1.用到工具:压缩壳 OD
2.特点:操作简单 免杀效果好
3.操作步骤:首先给木马加压缩壳 然后用OD载入,在入口处的前15句中NOP掉某些代码或者等价代换某些代码
【八.输入表免杀方法:】
[一,移位法]
1 首先用lordpe打开,目录,导入表找到你要改的函数。比如说CommandLineA
2 记下未改前函数的thunkvalue 举例:00062922
3 将要修改的文件用winhex等16进制形式打开,然后找到该函数的地址,比如说00062988
4 将该函数用00填充,移动到新地址如00070000
5 保存
6 将保存后的文件用lordpe打开,打开计算器,选择16进制,00062988-00062922+00070000,计算结果修改为新的thunkvalue。保存
注:公式-> 内存地址=RAV+RAV基址 ,RAV基地址可以在LORDPE中看到.输入表函数名前有两个空格所以RAV的地址要减去2
[二,修改字符法]
今天定位Drat2.9卡巴特征码,是在输入表上!(这时句废话,现在卡巴基本都杀输入表)
[特征] 00025175_00000001 ZwUnmapViewOfSection 他的特征码位置是函数后面的那个00
(这个函数我在开始移动过位置,原始DAT文件的特征码是0002516A_00000001,同样是函数后面的那个00)
我开始是选择C32移动位置,LordPE修改输入表,但是不行,后来试过OD指针移位,还是不行!CALL改JMP都不行
我发现LordPE可以修改函数名称!便用C32将ZwUnmapViewOfSection函数后面加了个字符b(你可以随意加字符)
由于LordPE读取输入表函数是从ThunkValue开始,一直到这个连续的字符串后的00处!
由于在ZwUnmapViewOfSection函数后加了个字符b,现在LordPE读取的此处函数为ZwUnmapViewOfSectionb
此时将ZwUnmapViewOfSectionb函数后面的那个b删除!保存下文件,这时就免杀了!
这样一修改,在文件00025175处的16进制代码不是00,而是62,所以卡巴就过了,而用lardPE修改后函数后,文件的输入表的函数还是ZwUnmapViewOfSection,生成服务端可以运行!
【免杀经验:】
1.加区,加花后,再加密,可以比较容易过卡巴----如加密工具vmprotect
脱壳过的木马---加花指令,或加区加花---加密---加压缩壳---再加区加花指令
2.单单加免杀花指令已经不能过卡巴,一定要配合加花后在加压缩壳,才能起到免杀卡巴的效果.
vmprotect加密----再加花-----可过卡巴:
3.加双层花指令免杀法----免卡巴
4.加密---007内存免----加压 ---免卡巴或内存.
5.双层加密(maskpE)---加压 ----可过卡巴.
6.maskpe加密---asppack加壳 ---改入口点加1---可过卡巴
7.加密maskpe----加花或加区加花(用工具)-----加压缩壳---免卡巴
8.北斗对黑防鸽子可加压二次,再压其它压缩壳.以达免杀.
9.加过北斗壳,向上拉滚开鼠标50多次,有一段空代码,可以加花,转移.
10.去头转移入口点---加花----加密(vmprotect) ----加压缩==过所有杀毒
11.对付卡巴,加免杀花指令.花指令对瑞星表面查杀一般无效,一般加压缩壳.
12.对付瑞星表面: 有些黑软,加区,加花后被瑞星表面杀,可以这样:先加压过瑞星表面,然后加免杀花指令,过卡巴.
13.过瑞星表面的查杀方法: 1.加北斗内存免杀压缩壳 2.加过瑞星表面的专用加密工具. 3.用maskPE加密工具加密 源码免杀,要求楼主必须会编程语言,如C语言,E语言等。可以载入IDA中调试,通过修改源码语句。
⑦ C语言 如何让任务管理器无法结束进程
HOOK TerminateProcess()这个API函数
我这里有源代码,要的话留邮箱
我先把主要的自定义类贴出来:
/////////////////////////////////////////////////////////
// APIHook.h文件
#ifndef __APIHOOK_H__
#define __APIHOOK_H__
#include <windows.h>
class CAPIHook
{
public:
CAPIHook(LPSTR pszModName,
LPSTR pszFuncName, PROC pfnHook, BOOL bExcludeAPIHookMod = TRUE);
virtual ~CAPIHook();
operator PROC() { return m_pfnOrig; }
// 实现
private:
LPSTR m_pszModName; // 导出要HOOK函数的模块的名字
LPSTR m_pszFuncName; // 要HOOK的函数的名字
PROC m_pfnOrig; // 原API函数地址
PROC m_pfnHook; // HOOK后函数的地址
BOOL m_bExcludeAPIHookMod; // 是否将HOOK API的模块排除在外
private:
static void ReplaceIATEntryInAllMods(LPSTR pszExportMod, PROC pfnCurrent,
PROC pfnNew, BOOL bExcludeAPIHookMod);
static void ReplaceIATEntryInOneMod(LPSTR pszExportMod,
PROC pfnCurrent, PROC pfnNew, HMODULE hModCaller);
// 下面的代码用来解决其它模块动态加载DLL的问题
private:
// 这两个指针用来将所有的CAPIHook对象连在一起
static CAPIHook *sm_pHeader;
CAPIHook *m_pNext;
private:
// 当一个新的DLL被加载时,调用此函数
static void WINAPI HookNewlyLoadedMole(HMODULE hMole, DWORD dwFlags);
// 用来跟踪当前进程加载新的DLL
static HMODULE WINAPI LoadLibraryA(PCSTR pszMolePath);
static HMODULE WINAPI LoadLibraryW(PCWSTR pszMolePath);
static HMODULE WINAPI LoadLibraryExA(PCSTR pszMolePath, HANDLE hFile, DWORD dwFlags);
static HMODULE WINAPI LoadLibraryExW(PCWSTR pszMolePath, HANDLE hFile, DWORD dwFlags);
// 如果请求已HOOK的API函数,则返回用户自定义函数的地址
static FARPROC WINAPI GetProcAddress(HMODULE hMole, PCSTR pszProcName);
private:
// 自动对这些函数进行挂钩
static CAPIHook sm_LoadLibraryA;
static CAPIHook sm_LoadLibraryW;
static CAPIHook sm_LoadLibraryExA;
static CAPIHook sm_LoadLibraryExW;
static CAPIHook sm_GetProcAddress;
};
#endif // __APIHOOK_H__
//////////////////////////////////////////////////////////////
// APIHook.cpp文件
#include "APIHook.h"
#include "Tlhelp32.h"
#include <ImageHlp.h> // 为了调用ImageDirectoryEntryToData函数
#pragma comment(lib, "ImageHlp")
// CAPIHook对象链表的头指针
CAPIHook* CAPIHook::sm_pHeader = NULL;
CAPIHook::CAPIHook(LPSTR pszModName, LPSTR pszFuncName, PROC pfnHook, BOOL bExcludeAPIHookMod)
{
// 保存这个Hook函数的信息
m_bExcludeAPIHookMod = bExcludeAPIHookMod;
m_pszModName = pszModName;
m_pszFuncName = pszFuncName;
m_pfnHook = pfnHook;
m_pfnOrig = ::GetProcAddress(::GetMoleHandle(pszModName), pszFuncName);
// 将此对象添加到链表中
m_pNext = sm_pHeader;
sm_pHeader = this;
// 在所有当前已加载的模块中HOOK这个函数
ReplaceIATEntryInAllMods(m_pszModName, m_pfnOrig, m_pfnHook, bExcludeAPIHookMod);
}
CAPIHook::~CAPIHook()
{
// 取消对所有模块中函数的HOOK
ReplaceIATEntryInAllMods(m_pszModName, m_pfnHook, m_pfnOrig, m_bExcludeAPIHookMod);
CAPIHook *p = sm_pHeader;
// 从链表中移除此对象
if(p == this)
{
sm_pHeader = p->m_pNext;
}
else
{
while(p != NULL)
{
if(p->m_pNext == this)
{
p->m_pNext = this->m_pNext;
break;
}
p = p->m_pNext;
}
}
}
void CAPIHook::ReplaceIATEntryInOneMod(LPSTR pszExportMod,
PROC pfnCurrent, PROC pfnNew, HMODULE hModCaller)
{
// 取得模块的导入表(import descriptor)首地址。ImageDirectoryEntryToData函数可以直接返回导入表地址
ULONG ulSize;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)
::ImageDirectoryEntryToData(hModCaller, TRUE,
IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);
if(pImportDesc == NULL) // 这个模块没有导入节表
{
return;
}
// 查找包含pszExportMod模块中函数导入信息的导入表项
while(pImportDesc->Name != 0)
{
LPSTR pszMod = (LPSTR)((DWORD)hModCaller + pImportDesc->Name);
if(lstrcmpiA(pszMod, pszExportMod) == 0) // 找到
break;
pImportDesc++;
}
if(pImportDesc->Name == 0) // hModCaller模块没有从pszExportMod模块导入任何函数
{
return;
}
// 取得调用者的导入地址表(import address table, IAT)
PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)(pImportDesc->FirstThunk + (DWORD)hModCaller);
// 查找我们要HOOK的函数,将它的地址用新函数的地址替换掉
while(pThunk->u1.Function)
{
// lpAddr指向的内存保存了函数的地址
PDWORD lpAddr = (PDWORD)&(pThunk->u1.Function);
if(*lpAddr == (DWORD)pfnCurrent)
{
// 修改页的保护属性
DWORD dwOldProtect;
MEMORY_BASIC_INFORMATION mbi;
::VirtualQuery(lpAddr, &mbi, sizeof(mbi));
::VirtualProtect(lpAddr, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect);
// 修改内存地址 相当于“*lpAddr = (DWORD)pfnNew;”
::WriteProcessMemory(::GetCurrentProcess(),
lpAddr, &pfnNew, sizeof(DWORD), NULL);
::VirtualProtect(lpAddr, sizeof(DWORD), dwOldProtect, 0);
break;
}
pThunk++;
}
}
void CAPIHook::ReplaceIATEntryInAllMods(LPSTR pszExportMod,
PROC pfnCurrent, PROC pfnNew, BOOL bExcludeAPIHookMod)
{
// 取得当前模块的句柄
HMODULE hModThis = NULL;
if(bExcludeAPIHookMod)
{
MEMORY_BASIC_INFORMATION mbi;
if(::VirtualQuery(ReplaceIATEntryInAllMods, &mbi, sizeof(mbi)) != 0)
hModThis = (HMODULE)mbi.AllocationBase;
}
// 取得本进程的模块列表
HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ::GetCurrentProcessId());
// 遍历所有模块,分别对它们调用ReplaceIATEntryInOneMod函数,修改导入地址表
MODULEENTRY32 me = { sizeof(MODULEENTRY32) };
BOOL bOK = ::Mole32First(hSnap, &me);
while(bOK)
{
// 注意:我们不HOOK当前模块的函数
if(me.hMole != hModThis)
ReplaceIATEntryInOneMod(pszExportMod, pfnCurrent, pfnNew, me.hMole);
bOK = ::Mole32Next(hSnap, &me);
}
::CloseHandle(hSnap);
}
// 挂钩LoadLibrary和GetProcAddress函数,以便在这些函数被调用以后,挂钩的函数也能够被正确的处理
CAPIHook CAPIHook::sm_LoadLibraryA("Kernel32.dll", "LoadLibraryA",
(PROC)CAPIHook::LoadLibraryA, TRUE);
CAPIHook CAPIHook::sm_LoadLibraryW("Kernel32.dll", "LoadLibraryW",
(PROC)CAPIHook::LoadLibraryW, TRUE);
CAPIHook CAPIHook::sm_LoadLibraryExA("Kernel32.dll", "LoadLibraryExA",
(PROC)CAPIHook::LoadLibraryExA, TRUE);
CAPIHook CAPIHook::sm_LoadLibraryExW("Kernel32.dll", "LoadLibraryExW",
(PROC)CAPIHook::LoadLibraryExW, TRUE);
CAPIHook CAPIHook::sm_GetProcAddress("Kernel32.dll", "GetProcAddress",
(PROC)CAPIHook::GetProcAddress, TRUE);
void WINAPI CAPIHook::HookNewlyLoadedMole(HMODULE hMole, DWORD dwFlags)
{
// 如果一个新的模块被加载,挂钩各CAPIHook对象要求的API函数
if((hMole != NULL) && ((dwFlags&LOAD_LIBRARY_AS_DATAFILE) == 0))
{
CAPIHook *p = sm_pHeader;
while(p != NULL)
{
ReplaceIATEntryInOneMod(p->m_pszModName, p->m_pfnOrig, p->m_pfnHook, hMole);
p = p->m_pNext;
}
}
}
HMODULE WINAPI CAPIHook::LoadLibraryA(PCSTR pszMolePath)
{
HMODULE hMole = ::LoadLibraryA(pszMolePath);
HookNewlyLoadedMole(hMole, 0);
return(hMole);
}
HMODULE WINAPI CAPIHook::LoadLibraryW(PCWSTR pszMolePath)
{
HMODULE hMole = ::LoadLibraryW(pszMolePath);
HookNewlyLoadedMole(hMole, 0);
return(hMole);
}
HMODULE WINAPI CAPIHook::LoadLibraryExA(PCSTR pszMolePath, HANDLE hFile, DWORD dwFlags)
{
HMODULE hMole = ::LoadLibraryExA(pszMolePath, hFile, dwFlags);
HookNewlyLoadedMole(hMole, dwFlags);
return(hMole);
}
HMODULE WINAPI CAPIHook::LoadLibraryExW(PCWSTR pszMolePath, HANDLE hFile, DWORD dwFlags)
{
HMODULE hMole = ::LoadLibraryExW(pszMolePath, hFile, dwFlags);
HookNewlyLoadedMole(hMole, dwFlags);
return(hMole);
}
FARPROC WINAPI CAPIHook::GetProcAddress(HMODULE hMole, PCSTR pszProcName)
{
// 得到这个函数的真实地址
FARPROC pfn = ::GetProcAddress(hMole, pszProcName);
// 看它是不是我们要hook的函数
CAPIHook *p = sm_pHeader;
while(p != NULL)
{
if(p->m_pfnOrig == pfn)
{
pfn = p->m_pfnHook;
break;
}
p = p->m_pNext;
}
return pfn;
}
如果你对HOOK API有一顶的了解m就可以用这个类来实现你的程序:
最重要的2个接口:
static void ReplaceIATEntryInAllMods(LPSTR pszExportMod, PROC pfnCurrent,
PROC pfnNew, BOOL bExcludeAPIHookMod);
HOOK所有模块
static void ReplaceIATEntryInOneMod(LPSTR pszExportMod,
PROC pfnCurrent, PROC pfnNew, HMODULE hModCaller);
HOOK 指定模块
你只要能使所有进程都HOOK所有模块,就能达到你的目的
<很明显利用全局钩子嘛>
把你要HOOK的代码放到DLL里面,让所有进程加载,就能实现了
⑧ 用软件做免杀改特征码的方法
一、主动免杀1. 修改字符特征:主动查找可能的特征码,包括木马文件修改注册表、生成新文件的名称与路径、注入的进程名等动作,也包括运行过程中可能出现或一定会出现的字符等文件特征。然后找出这些字符,并将其修改。2. 修改输入表:查找此文件的输入表函数名(API Name),并将其移位。3. 打乱文件结构:利用跳转(JMP),打乱文件原有结构。4. 修改入口点:将文件的入口点加1。5. 修改PE段:将PE段移动到空白位置二、被动免杀1. 修改特征码:用一些工具找出特征码并针对特征码做免杀处理。2. 用Vmprotect:使用Vmprotect加密区段。3. 文件加壳:可以用一些比较生僻的壳对木马文件进行保护。有的朋友看到这里有可能蒙了,PE、Vmprotect、入口点……这些都是什么意思啊?不要着急,下面我会一一介绍的,只要你看完这篇文章,就一定会成为免杀高手!怎么样?Go!3.实战演习1.)修改字符特征好,下面我们依然以一个病毒防御工作者的角度来考虑我们每一步应该做什么,然后在利用逆向思维分而治之。现在假如我们拿到一个木马样本灰鸽子,首先当然要分析它究竟有什么功能,怎样运行以及怎样保护自己等。其实这一步要求的专业知识是很多的,但考虑到我们的读者,我们暂且用一个比较简单易行的方法——运行木马AND查看此程序的帮助文档。我们打开RegSnap,新建一个快照,打开RegSnap后,点击[新建快照]按钮(如图1)。
在弹出的对话框中选择[生成所有项目的快照](如图2)。然后保存快照,现在已经将RegSnap配置好了,下面运行我们的木马程序(提醒:做免杀时,一定要记住养好随时备分的好习惯,以防止修改错误或是实验运行时破坏、删除木马)。木马运行完毕后,我们在按照上面的方法重新做一个快照并保存,然后按快捷键F5,在弹出的“比较快照”对话框中选择刚才保存的快照,在“第一个快照”中选择我们刚才第一次保存的快照,而“第二个快照”选择我们后保存的快照存档,很快结果就出来了(如图3)。
有的朋友对于使用RegSnap收集到的信息感到无力分析,抱怨收集到的东西太多,在这里我简单的介绍一下,首先应注意的是生成做对比的两个快照之间的时间要尽可能短,另外要排除带有OpenSaveMRU的注册表键值,还要排除有关*.rsnp文件的创建读写等操作记录。下面我们就将有用的信息提取出来,逐一分析。文件列表于 C:\WINDOWS\*.*新增文件木马.exe注册表报告新增主键HKEY_CURRENT_USER\Software\Microsoft\Windows\ShellNoRoam\MUICache\C:\Documents and Settings\A1Pass-admin\桌面\huigezi\复件 Server02.exe键值: 字符串: "复件 Server02"HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\Root\LEGACY_*6728*9A6C*670D*52A1\0000\Class键值: 字符串: "LegacyDriver"HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\Root\LEGACY_*6728*9A6C*670D*52A1\0000\ClassGUID键值: 字符串: "{8ECC055D-047F-11D1-A537-0000F8753ED1}"HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\Root\LEGACY_*6728*9A6C*670D*52A1\0000\Control\ActiveService键值: 字符串: "木马服务"HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\木马服务\Description键值: 字符串: "灰鸽子服务端程序。远程监控管理."……这里我只摘录了部分关键性的木马动作记录,全部记录请见光盘。通过文件列表我们可以知道木马在WINDOW目录下生成了一个新文件,而通过注册表的监控信息我们也知道了木马是怎样将自己注册为系统服务并自动运行的。那么我们回到瑞星的研究分析室,看看那些大哥大姐们会怎么办……瑞星大哥:“最近这灰鸽子太猖狂啦!我们是不是应该多定义几套特征码?”瑞星大姐:“恩,不错!先在注册表那定义一套特征码在说吧。”A1Pass:“STOP!!”(只见画面突然定格,A1Pass将播放器最小化。)通过上面的对话,我们可以知道他们要将注册表的某个字符定义为特征码,从上面RegSnap分析出来的记录来看,他们的选择真的是太多了!那么他们究竟会用到哪些呢?其实,就做为一个黑客来讲,只要不影响服务端正常运行,就应该尽量多的改掉木马的所有字符,当然全部改变是不可能的,除非你自己编写木马。有的朋友要问了,除了注册表别的就不可以改了吗?答案当然是否定的,譬如生成新文件的名称与路径、注入的进程名等动作,这些我们可以利用WINDOWS对字母大小写不敏感的这一特点直接替换字母的大小写,而对于运行过程中可能出现或一定会出现的字符等我们可以直接将其替换成别的内容。下面我为大家演示一下怎样更改注入进程的名称。首先配置服务端,通过图4我们可以看出来灰鸽子的启动运行是需要“IEXPLORE.EXE”这个进程的,根据注册表的推理,我们可以认为其未加壳的服务端是应该存在“IEXPLORE.EXE”这一字符串的。既然如此,我们就先请出我们的第一把武器“WinHex”!
WinHex是一款极为出名16进制编辑器。得到 ZDNetSoftwareLibrary 五星级最高评价,拥有强大的系统效用。在这里,我们只用它来编辑文件,其余不做过多讨论。首先我们用WinHex打开我们的木马文件“Server.exe”,打开后如图5所示。
然后我们按[Ctrl]+[F]快捷键调出查找文本对话框,输入IEXPLORE.EXE后点击“是”(如图6)。
结果如图7所示。下面我们就对其进行大小写转换,用鼠标点击要更改的字母(例如I),然后在按键盘上的i,即可完成更改,就象使用WINDOWS的记事本一样。更改完毕后,按[Ctrl]+[S]快捷键保存即可。
就这么简单?对!就这么简单!其他的例如注册表、生成新文件的名称与路径等等都可以利用此方法更改。但是不幸的是,经过这样改后,还不足以对付例如金山、江民等品牌杀毒软件,要想对付这些杀毒软件的查杀,我们还需要对我们的木马进行进一步处理。下面,我们开始学习输入表函数(APIName)免杀!2.)修改输入表不知有的朋友是否知道,PE文件的正常运行是离不开其内部输入表函数的,而不同的程序,其内部输入表函数的名称与在文件中的位置是不一样的,所以输入表函数也成了病毒防御工作者制作特征码紧盯的地方之一。在我查出来的关于灰鸽子的特征码来看,“瑞星大哥”已经将其的一处输入表函数作为特征码了。所以掌握输入表函数免杀技巧对于新入门的朋友来说势在必行!
[PE文件小知识:PE文件是WINDOWS系统中特有的一种文件结构,它包括PE文件头、输入表与相关资源文件等等]经过我的测试,直接单独修改文件内部的输入表函数会导致程序运行不正常甚至崩溃!那就没有办法了吗?我可没那么容易认输!经过一翻苦战,终于让我在LordPE中找到了解决办法,同时FoBnN的文章也给了我非常大的启发……我们先打开LordPE,点击[PE编辑器]按钮,在弹出的对话框中选中木马文件,打开后点击[目录](如图8)。在点击导入表后面的[…](如图9)。在弹出的对话框中我们选择wininet.dll下的InternetOpenUrlA(如图10),有的朋友要问了,为什么非选择InternetOpenUrlA这个输入表函数呢?呵呵!那是因为这个输入表里有特征码哦,关于怎样确定特征码,我在后面会介绍,大家先别着急。
好的,关于LordPE就先停在这,下面我们就用WinHex来查找InternetOpenUrlA这个输入表函数的所在位置,并将其用0填充(操作方法:单击WinHex右面的16进制信息,输入0即可)(如图11、12)。
然后将其写到空白区域(既显示000000的区域),一定要从头开始写入,这样在以后计算地址时不容易出错,除此之外也要注意输入表函数的大小写不要搞错(如图13)。保存后我们在回到LordPE那里,在需要更改的InternetOpenUrlA输入表函数上单击右键,在弹出的菜单里选择“编辑”,将Thunk里的信息改成000B9D5E(如图14)即可。有的朋友要问了,刚才我们不是把那个输入表函数放到000B9D60那里了吗?到这怎么变成000B9D5E了?其实原理很简单,因为每个输入表函数前面都是有一个空格的,我们虽不用真正把那个空格加进去,但填写它的地址时一定要空出来,否则就会出错!而将000B9D60减去一个空格所占的位置,其地址正好为000B9D5E,还不十分明白的朋友在仔细看看图13,下面我们在回到LordPE,看看我们改过的输入表函数变成什么样了(如图15)?呵呵!那我们该怎么办呢?其实简单的很,只要在重新改一下输入表函数的名称就可以了(如图16)。有的时候因为我们所填写的地址为比较靠后的,例如我们现在改的这个000B9D5E,后面仅能容纳两个字节,所以更改输入表函数时只能键入两个字,对于这种情况我们可以先把Thunk里的信息改成如000B9D60这样的起始地址,改输入表函数名更改完毕后在将000B9D60改回原来的值(既000B9D5E),保存后即可成功,我们试一下看看(如图17)。经测验鸽子的各项功能均正常!在用瑞星查一下试试(如图18),结果当然不言而喻……
3.)修改特征码虽然到这我们免杀已经成功,但是为了学到更多的技术,为了让我们免杀的鸽子存活的更久,下面我在为大家介绍一下特征码的查找与修改技巧。特征码是杀毒软件的心脏,但同样也是我们的心脏!就看谁先找到对方地心脏,并能发出致命一击,谁就是胜利者!一提到查找特征码,就不得不说说MyCCL与CCL,这两个软件的名字相信留心过免杀技术的朋友不会陌生,但由于软件操作的傻瓜化,很多时候对于CCL的介绍只是一带而过,这可苦了入门的朋友!这一小节我就先介绍一下MyCCL的用法……我们先来认识一下MyCCL(如图19),根据这张图我们下面就来大体介绍一下MyCCL的应用方法。首先点击第1处选择文件,然后在第2处输入分块个数,分块个数越多,定位越精确,然而生成的速度同时也就越慢,生成的文件总体积也就越大,就象灰鸽子这么大的服务端,如果分块数为300的话,那么它生成文件的总体积将超过230M!所以在这里不建议填写太大的数字,一般象灰鸽子这样的服务端分块数填400个就足够了。生成完毕后会弹出个对话框提醒你去相应目录杀毒,图中所示为“E:\文章\极度免杀\鸽子\OUTPUT”文件夹,我们到那个文件夹下开始杀毒,查到病毒就让杀毒软件将其彻底删除,注意,这一点很重要!处理完毕后点击第3处的二次处理,在点击[生成]上面的[特征区间]按钮即可出现右面的对话框。下面我们在“区间设定”里右键单击特征码区间,在弹出的菜单中选择“复合精确定位此处特征”(如图20),然后重复上面的操作,直到你认为[单位长度]已经小到很方便更改的时候,特征码的定位就算结束了。好了,一口气说了这么多,不知道刚入门的朋友是否懂得一些MyCCL的用法了没有……但是上面我们定位的是文件特征码,还有内存特征码没有定义,这里我们要用到CCL的内存特征码定位功能,打开CCL后,我们依次选择[文件]→[特征码验测]→[内存特征码](如图21)。
在弹出的对话框中选择我们要进行免杀操作的木马,然后会进入“定位范围选择窗口”(如图22)。由图中可知,第一个CODE段的偏移量为00000400,也就是说我们可以用00000400做为起始位置,那么我么就在用户输入区的“起始位置”处填写00000400,下面的那个验测大小怎么填写呢?看到图22中画线的那个“当前文件大小”了吗?我们可以用WINDOWS系统自带的计算器进行计算,把计算器的“查看”菜单设置为科学型、十六进制、四字(如图23)。然后用当前文件大小的值减去起始值00000400,得到的结果为000B9A00,那么我们就在“验测大小”后填上000B9A00,然后点击“填加区段”按钮(如图24)。最后点击确定,在新弹出的对话框中点击运行,不过需要注意的是,在进行此步操作时一定要打开杀毒软件的所有功能。下面你要做的就是等待……然而光找特征码是不够的,我们还得学会怎样更改,而关于特征码地更改是非常有学问的!这里为了方便广大读者能学以致用,在此我只介绍部分理论知识,着重介绍实践操作,但是我想请大家注意,免杀的方法象你做完免杀的木马一样,都有生存时间,而过了这个时间,这种免杀方法就变的不在实用,或者免杀效果大打折扣!所以要想真正成为免杀高手,还的打牢基本功,不断创造出新的免杀方法,因为我们是在与杀毒软件厂商的专业技术人员“斗法”啊!关于需要注意的问题就先讲的这,下面我带大家先来了解一下目前更改特征码的办法。1. 大小写替换(只适用于文件免杀)适 用 于:出现可识别的英文字母或词组,并且确定其不是相关函数(如输入表函数)。操作方法:如咱们“实战演习”的第一节讲的一样,只须将大小写替换一下就可以了,例如特征码中出现了A,你只要将其替换为a即可。原 理:利用WINDOWS系统对大小写不敏感,而杀毒软件却对大小写非常敏感这一特性达到免杀目的。2. 用00填充适 用 于:几乎任何情况,但成功率不是非常高。操作方法:例如我们找到了一处特征码0009EE7F_00000005,那么根据这段特征码信息我们可以知道它的位置在0009EE7F,大小为5个字节,也就是0009EE7F-0009EE83这一段内容(如图25)。
一直跟着文章实践操作的朋友肯定有疑问,你是怎么找到那个地址的呢?而我怎么找不到呢?那是因为WinHex的默认偏移量为decimal模式,我们单击Offset栏将其改为16进制模式即可(如图26)。
然后我们有选择的一处处地用00填充(如图27)。记住要多试几次,80%的情况下你都能找到一处既能免杀又不影响程序正常运行的区域。对于定义出的内存特征码,只要将其内存地址用一个叫做《便宜量转换器》的小程序转换成16进制偏移量,然后在进行相应操作即可。原 理:由于PE文件的特殊格式以及程序编译语言等问题,使得生成目标代码的效率并不高,难免出现一些“垃圾信息”,而这些信息存在与否对与程序是否能正常运行并不起决定性的作用,而当木马的这部分“垃圾信息”被定义为特征码时,我们完全可以将其删除,而删除的方法就是用无任何意义的00将其替换。3. 跳到空白区域适 用 于:几乎任何情况,成功率比较高。操作方法:还是以特征码0009EE7F_00000005为例子,假如我们使用00填充的方法失败了那么不要多想,接下来马上试试OllyDbg,关于OllyDbg我就不多介绍了,它是非常棒而且非常专业的一个动态反汇编/调试工具,这里我们只用它来帮助我们进行免杀作业,首先应该做的就是将我们的16进制偏移量0009EE7F转换为内存地址,因为OllyDbg的工作原理是先将程序释放到内存空间里,然后才能进行相关作业…这里要用到的是一个叫做《便宜量转换器》的小程序,我们用其转换完毕后得到的内存地址为0049FA7F(如图28)。
下面我们用OllyDbg打开我们的木马服务端,首先找到一处空白区,并域记下这的地址004A24A5,然后找到我们刚转换过来的地址0049FA7F,先将以0049FA7F开始以下的这三行数据选定,然后单击右键选则[复制]→[到接剪贴板](如图29)。将其复制到本文文档里备用,然后在将这三行代码一一NOP掉(如图30)。最后右键点击0049FA7F,在弹出的对话框中选择汇编,并写入“jmp 004A24A5”这条汇编指令(如图31)。记住,在点击[汇编]按钮之前一定先把“使用 NOP 填充”前面的勾去掉。然后我们记下汇编后0049FA7F的下面那个地址0049FA84(仔细观察图31)。好,下面我们回到004A24A5这处刚才找到的空白地址(如图32)。
然后用刚才汇编的方法把在本文文档里备用的信息一句句地汇编进去,然后在将最后一句代码的下一行004A24AA处加入“jmp 0049FA84”这行代码(如图33)。然后单击右键→[复制到可执行文件]→[所有修改](如图34)。
在弹出的对话框中选择“全部复制”然后保存即可。而对于内存免杀就省去了内存地址转换这一步了。原 理:大家先看图35,由图中可知,正象此方法的名字“跳到空白区域”一样,这种方法的原理就是将原本含有特征码的信息转移到空白区域,并把原先位置的信息全部NOP掉,并在那里加一个跳转指令,让其跳到004A24A5处,也就是我们找到的空白区域,并把原来在0049FA84的信息移到这里,加完信息后在加一条指令让其在跳回去,以使程序连贯起来。
4. 上下互换适 用 于:几乎任何情况,成功率比较高。操作方法:先用OllyDbg载入木马程序,假定其特征码为0009EE7F_00000005,我们还是先用《偏移量转换器》将其转换为内存地址,上面我们已经知道0009EE7F对应的内存地址为0049FA7F,然后在OllyDbg中找到相应位置,利用上面“跳到空白区域”里介绍的修改方法将0049FA7F上下两句代码调换位置即可。而对于内存免杀就省去了内存地址转换这一步了。原 理:杀毒软件的特征码定位是严格按照相关偏移量于内存地址进行的,而其实我们的应用程序中的机器码执行顺序的先后在一般情况下是没有死规定的,所以我们只需将其上下互换,杀毒软件自然就不认识了。5.ADD与SUB 互换适 用 于:在内存特征码中出现ADD或 SUB指令的,成功率比较高。操作方法:用OllyDbg载入木马程序,假定其特征码所对应的地址中有ADD或SUB指令,例如00018A88:XXXXX 00000088 ADD ECX 10000000我们可以将ADD ECX 10000000这段机器码改为SUB ECX F0000000,更改完毕后保存为EXE文件即可。原 理:我们都知道1+1=2,我们也知道1-(-1)=2,上面就是利用了这个原理,其中ADD指令的就是加意思,而SUB则是减的意思。虽然被我们互换了一下,但是最终结果还是一样的,可是换完之后杀毒软件就不认识了。到这里,关于特征码的查找与修改就讲完了,但是除此之外呢?答案是还有许多!!下面我们就一起看看其他免杀方法。4.)其他免杀方法改文件头:这里所说的改文件头包括加头去头,文件加花。关于加头去头,我们还是用OllyDbg。用OllyDbg载入后,OllyDbg会自动停在入口点(如图36)。
我们将头三行机器码复制保存起来,然后找到空白区域,用汇编的方法一一将其写入(如图37)。然后在后面写入一条JMP指令,让其跳到初始入口点的第四行,相信一直仔细看本文的朋友一定明白其原理,如果忘了的话可以看上面修改特征码的第三种方法,原理与这差不多,修改完毕后如下所示:004A2A73 0000 add byte ptr ds:[eax],al004A2A75 0000 add byte ptr ds:[eax],al004A2A77 55 push ebp004A2A78 8BEC mov ebp,esp004A2A7A B9 04000000 mov ecx,4004A2A7F ^ E9 CCF3FFFF jmp Server.004A1E50004A2A84 0000 add byte ptr ds:[eax],al004A2A86 0000 add byte ptr ds:[eax],al004A2A88 0000 add byte ptr ds:[eax],al
上面的add byte ptr ds:[eax],al就是所谓的空白区域,我们看到改完后的头文件位于004A2A77,所以我们还要用PEditor改一下入口点,打开PEditor后载入文件,将入口点处的地址改为我们的新文件头地址004A2A77(如图38),保存后即可。
⑨ c语言中可以用public和protect吗
public和protect不是C语言的关键字,你可以用他们做标识符使用。public、protect一般用在面向对象语言中,表示类的访问权限。C语言不是面向对象的。
⑩ c语言如何将一段自定义的buff转换成可执行的代码
__declspec(noinline)voidhelloworld()
{
printf("helloworld");
"helloworld"(4221E0h)
004017C5E878A40000callprintf(40BC42h)
004017CA59popecx
}
因为代码生成的汇编指令call是相对位置的
E8 78 A4 00 00 这个, e8表示相对地址调用,后面78 A4 00 00 表示的 当前的地址和printf函数地址的偏移。
如果自己memcpy复制后,helloworld函数的地址变了,那个call指令和 printf函数的偏移距离也变了。所以就出错了。
所以这个复制代码的方式要正常工作的话,这段代码必须是位置无关的,也就是
Position-independentcode
gcc里面可以指定pic选项来让编译器生成位置无关的代码。vc里面找了一下没找到。
所以只能使用汇编才行了。
charformat[]="%s%s ";
charhello[]="Hello";
charworld[]="world";
staticintprintf_addr=(int)&printf;
__declspec(noinline)voidhelloworld()
{
//printf("helloworld");
__asm
{
moveax,offsetworld
pusheax
moveax,offsethello
pusheax
moveax,offsetformat
pusheax
//callprintf
moveax,printf_addr
calleax
//
//
popebx
popebx
popebx
}
}
这样写之后,这个call指令那里,生成的机器码采用的是绝对值的FF,就可以正常工作了。
所以这种用法的话,还是自己手写位置无关的汇编才行,或者需要会自己做重定位的。就像上面那个一样 自己知道call指令的那里的话,可以自己修改偏移为正确的值。