Sunday, August 7, 2011

FSD inline hook

Anthor:hfyy
Time:2008-05-13 19:32:44

This is unfinished code,I wanted to hide file,But The code turn up question to worte specific for hide file.So Pubilish to help,


code:
#include "ntddk.h"

typedef BOOLEAN BOOL;
typedef unsigned long DWORD;
typedef DWORD * PDWORD;
typedef unsigned long ULONG;
typedef unsigned short WORD;
typedef unsigned char BYTE;

typedef struct _FILE_BOTH_DIR_INFORMATION {
    ULONG NextEntryOffset;
    ULONG FileIndex;
    LARGE_INTEGER CreationTime;
    LARGE_INTEGER LastAccessTime;
    LARGE_INTEGER LastWriteTime;
    LARGE_INTEGER ChangeTime;
    LARGE_INTEGER EndOfFile;
    LARGE_INTEGER AllocationSize;
    ULONG FileAttributes;
    ULONG FileNameLength;
    ULONG EaSize;
    CCHAR ShortNameLength;
    WCHAR ShortName[12];
    WCHAR FileName[1];
} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;

typedef struct tag_QUERY_DIRECTORY
{
  ULONG Length;
  PUNICODE_STRING FileName;
  FILE_INFORMATION_CLASS FileInformationClass;
  ULONG FileIndex;
} QUERY_DIRECTORY, *PQUERY_DIRECTORY;

typedef struct  _REQINFO{
  PIO_COMPLETION_ROUTINE    OldCompletion;
} REQINFO,*PREQINFO;

NTSYSAPI NTSTATUS
ObReferenceObjectByName(
            IN PUNICODE_STRING ObjectPath,
            IN ULONG Attributes,
            IN PACCESS_STATE PassedAccessState OPTIONAL,
            IN ACCESS_MASK DesiredAccess OPTIONAL,
            IN POBJECT_TYPE ObjectType,
            IN KPROCESSOR_MODE AccessMode,
            IN OUT PVOID ParseContext OPTIONAL,
            OUT PVOID *ObjectPtr);

typedef  NTSTATUS  (*OLDIRPMJDIRECTORYCONTROL)(IN PDEVICE_OBJECT,IN PIRP);



NTSTATUS HookFastFat();//hook fastfat.sys
NTSTATUS MyCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context);//完成示例
VOID write();//写入补丁
VOID write_back();//写回补丁
NTAPI MyDirectoryControl();//这个函数将inline在IRP_MJ_DIRECTORY_CONTROL之前
NTSTATUS Check();//测试一下  其实是硬编码 如果想应用在不同平台 需要改进


PDRIVER_OBJECT  pFile=NULL;//fastfat的PDRIVER_OBJECT
OLDIRPMJDIRECTORYCONTROL  OldIrpMjDirectoryControl;//原来的MajorFunction[IRP_MJ_DIRECTORY_CONTROL]
BOOL hook;//hook标志
PIO_STACK_LOCATION  irpStack;
DWORD        context;//这个用来传递完成示例的地址

// This is our unload function

VOID OnUnload( IN PDRIVER_OBJECT DriverObject )

{

    DbgPrint("OnUnload called\n");
  if (hook)
  {
    write_back();
  }
  //这里我用的方法是inline hook 还可以用下面方法hook IRP
  /*if (OldIrpMjDirectoryControl&&pFile)
  {
    InterlockedExchange((PLONG)&pFile->MajorFunction[IRP_MJ_DIRECTORY_CONTROL],(LONG)OldIrpMjDirectoryControl);
  }*/

}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,

                     IN PUNICODE_STRING theRegistryPath)

{
    NTSTATUS ntStatus;
    DbgPrint("I loaded!");
    ntStatus=HookFastFat();
    if(!NT_SUCCESS(ntStatus))
      return  ntStatus;
      // Initialize the pointer to the unload function

      // in the DriverObject

    theDriverObject->DriverUnload  = OnUnload;

    return STATUS_SUCCESS;

}
//hook fastfat.sys
NTSTATUS HookFastFat()
{
  char *p;
  int  i;
  NTSTATUS ntStatus;
  UNICODE_STRING  sFastFat;
  WCHAR  FastFatBuffer[]=L"\\FileSystem\\Fastfat";
  RtlInitUnicodeString(&sFastFat,FastFatBuffer);
  //得到pFile
  ntStatus=ObReferenceObjectByName(&sFastFat,
                  OBJ_CASE_INSENSITIVE,NULL,0,
                  ( POBJECT_TYPE )IoDriverObjectType,
                  KernelMode,NULL,&pFile);
 
  if(!NT_SUCCESS(ntStatus))
    return ntStatus;
  //保持一下旧的MajorFunction[IRP_MJ_DIRECTORY_CONTROL]
  OldIrpMjDirectoryControl=pFile->MajorFunction[IRP_MJ_DIRECTORY_CONTROL];
  p=(char *)OldIrpMjDirectoryControl;
  //函数地址change hook
  /*if (OldIrpMjDirectoryControl)
  {
    InterlockedExchange((PLONG)&pFile->MajorFunction[IRP_MJ_DIRECTORY_CONTROL],(LONG)MyControl);
  }*/
  //DbgPrint("%08X",p);
  /*for(i=0;i<7;i++)
  {
    DbgPrint("-0x%02X",(unsigned char)p[i]);
  }*/
  //在此处将补丁写入 将hook标志置TRUE
  if(NT_SUCCESS(Check()))
  {
    DbgPrint(" check SUCCESS");
    write();
    hook=TRUE;
  }
  else
    DbgPrint(" check UNSUCCESSFUL");
  return  ntStatus;
}
//测试一下
NTSTATUS Check()
{
  int i=0;
  char *p=(char *)OldIrpMjDirectoryControl;
  char c[]={0x6a,0x18,0x68,0x20,0x3d,0xd8,0xf9};
  for(;i<7;i++)
  {
    DbgPrint("-0x%02X",(unsigned char)p[i]);
    if(p[i]!=c[i])
    {
      return STATUS_UNSUCCESSFUL;
    }
  }
  return STATUS_SUCCESS;
}

//写入补丁
VOID write()
{
  KIRQL oldIrql;
  char *actual_function=(char *)OldIrpMjDirectoryControl;
  char *non_paged_memory;
  unsigned long detour_address;
  unsigned long reentry_address;
  int i = 0;
  //jmp 11223344
  char newcode[] = { 0xEA, 0x44, 0x33, 0x22, 0x11, 0x08, 0x00 };
  //要返回的地址是原来地址+7
  reentry_address = ((unsigned long)OldIrpMjDirectoryControl) + 7;
  //分配空间 要是NonPagedPool
  non_paged_memory = ExAllocatePool(NonPagedPool,1024);
  //将补丁写入non_paged_memory
  for(i=0;i<1024;i++)
  {
    ((unsigned char *)non_paged_memory)[i] = ((unsigned char *)MyDirectoryControl)[i];
  }
  //将地址保持在detour_address
  detour_address = (unsigned long)non_paged_memory;
  //将11223344替换为真正补丁地址
  *( (unsigned long *)(&newcode[1]) ) = detour_address;

  //将AAAAAAAA替换为真正的返回地址
  for(i=0;i<1024;i++)
  {
    if( (0xAA == ((unsigned char *)non_paged_memory)[i]) &&
      (0xAA == ((unsigned char *)non_paged_memory)[i+1]) &&
      (0xAA == ((unsigned char *)non_paged_memory)[i+2]) &&
      (0xAA == ((unsigned char *)non_paged_memory)[i+3]))
    {
      // we found the address 0xAAAAAAAA
      // stamp it w/ the correct address
      *( (unsigned long *)(&non_paged_memory[i]) ) = reentry_address;
      break;
    }
  }
  oldIrql = KeRaiseIrqlToDpcLevel();
  //写入补丁了
  __asm
  {
            push eax
            mov  eax, CR0
            and  eax, 0FFFEFFFFh
            mov  CR0, eax
            pop  eax
    }

  for(i=0;i < 7;i++)
  {
    actual_function[i] = newcode[i];
  }

  __asm
    {
            push eax
            mov  eax, CR0
            or   eax, NOT 0FFFEFFFFh
            mov  CR0, eax
            pop  eax
    }
  KeLowerIrql(oldIrql);
}
//写回
VOID write_back()
{
  KIRQL oldIrql;
  char *actual_function=(char *)OldIrpMjDirectoryControl;
  //将原来的指令写回 此处用的硬编码
  char c[]={0x6a,0x18,0x68,0x20,0x3d,0xd8,0xf9};
  int i;
  oldIrql = KeRaiseIrqlToDpcLevel();
  __asm
  {
            push eax
            mov  eax, CR0
            and  eax, 0FFFEFFFFh
            mov  CR0, eax
            pop  eax
    }

  for(i=0;i < 7;i++)
  {
    actual_function[i] = c[i];
  }

  __asm
    {
            push eax
            mov  eax, CR0
            or   eax, NOT 0FFFEFFFFh
            mov  CR0, eax
            pop  eax
  }
  KeLowerIrql(oldIrql);
}
//此处为naked 函数 防止编译器放入额外操作码
__declspec(naked) NTAPI MyDirectoryControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
  __asm
  {   
      pushad
      pushfd
  }
  //此处设置IRP CompletionRoutine并将原来的CompletionRoutine地址保存放入context
  irpStack=IoGetCurrentIrpStackLocation(Irp);
  irpStack->Control = 0;
  irpStack->Control |= SL_INVOKE_ON_SUCCESS;
  irpStack->Context=(PIO_COMPLETION_ROUTINE)ExAllocatePool(NonPagedPool,sizeof(PREQINFO));
  ((PREQINFO)irpStack->Context)->OldCompletion=irpStack->CompletionRoutine;
  irpStack->CompletionRoutine=(PIO_COMPLETION_ROUTINE)MyCompletionRoutine;
  __asm
  {   
      popfd
      popad
  }
  __asm
  {   
    // exec missing instructions
    push  18h
    push    0F9D83D20h
  }
    // jump to re-entry location in hooked function
    // this gets 'stamped' with the correct address
    // at runtime.
    //
    // we need to hard-code a far jmp, but the assembler
    // that comes with the DDK will not poop this out
    // for us, so we code it manually
    // jmp FAR 0x08:0xAAAAAAAA
  __asm
  {
    _emit 0xEA
    _emit 0xAA
    _emit 0xAA
    _emit 0xAA
    _emit 0xAA
    _emit 0x08
    _emit 0x00
  }
}
//CompletionRoutine
NTSTATUS MyCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)
{
  PIO_COMPLETION_ROUTINE old;
  old=((PREQINFO)Context)->OldCompletion;
  DbgPrint("MyCompletionRoutine called");
  ExFreePool(Context);
  if ((Irp->StackCount>(ULONG)1)&&(old!=NULL))
  {
    return  (old)(DeviceObject,Irp,NULL);
  }
  else
    return  Irp->IoStatus.Status;
}

How to bypass message break

Anthor:RYYMike
Guess one:Through window subclass to operate
Checking:That is Impossible .Subclassing operation need to windows receive massage.To do so would still be broken,code of function also point to processing message code after broken,so no to bypass effect of message breaking.

Guess two:Through hooking to operate
Preliminary idea:First step use SetWindowsHookEx intercept and capture message first,After that,Intercept of Message dispense to original windows,Modified msg's parameter.

Question:How to realized message breaking of OLLDBG?If message breaking through to hooking created yet,Depending on specialty of hooking installation: 根据钩子的安装特点:First installation in the behind after the installation,in the front,So debugger's message breaking before execute hook function oneself be breaked yet.

Confirmation:Through create one windows oneself,According to the above hook and don't return breaking,That demonstrate message breaking not through created hooking to realize.
examples://C++
#include <windows.h>
  HWND HookHwnd;         //Hooked windows
  UINT HookMsg;          //sub-definite windows's msg
  int HookBool;          //Window is be created or be called
    WNDPROC HookProc;      //Old address
  HHOOK HookID;          //
    char StoreString[50];  //Return import string
LRESULT  CALLBACK AvoidProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam){//Escape hooked function
  if(lParam&0x80000000){//Enter one key generate two event:WM_KEYDOWN和WM_KEYUP,So removed one
    if(Msg== HookMsg){//
static int n;                                                   //
static char HideString[50];                          
HideString[n]='*';
StoreString[n]=wParam;
n=n+1;                                                        //
SetWindowText(hwnd,HideString);             //“*”
    return 1;                   
    }
  }
return CallWindowProc ((WNDPROC)HookProc,hwnd,Msg,wParam,lParam);//Call old window
 
}

LRESULT   CALLBACK MessageHook(int nCode,WPARAM wParam,LPARAM lParam){//Hooking callback function
    if (GetFocus()==HookHwnd){//判断输入焦点是不是想逃脱断点的窗口
        if (HookBool==1){
          static int Count;//判断是否已进行过GetWindowLong
          if (Count==0){
         HookProc=(WNDPROC)GetWindowLong(HookHwnd,GWL_WNDPROC);                                          //得到以前的窗口
   HookProc = (WNDPROC)SetWindowLong(HookHwnd, GWL_WNDPROC, (LONG)AvoidProc);//窗口子类化
          Count=1;
          }
          }
  PostMessage(HookHwnd,HookMsg,wParam,lParam);//传递消息
    }
return 1;
}

int MessageBreakAvoid(HWND hwnd,UINT msg,int Bool){//挂钩的函数,并进行一些初始化
  HookHwnd=hwnd;                         //初始化
  HookMsg=msg;   
    HookBool=Bool;
  HookID=SetWindowsHookEx(WH_KEYBOARD,MessageHook,GetModuleHandle(NULL),GetCurrentThreadId());//进行挂钩
return 0; 
}

int UnMessageBreakAvoid(){//删除钩子
  UnhookWindowsHookEx(HookID);
return 0; 
}
Next code followed by above code,example to do,

int PASCAL  WinMain(HINSTANCE MyHinst,HINSTANCE hPrev,LPSTR CmdLine,int ShowNumber){
HWND hwndB=CreateWindow("edit","个人简介",WS_VISIBLE,20,130,950,950,NULL,NULL,MyHinst,NULL);
ShowWindow(hwndB,1);
UpdateWindow(hwndB);
MSG MyMsg;
MessageBreakAvoid(hwndB,1101,1);                     ///注意这里
while (GetMessage(&MyMsg, NULL, 0, 0))
{
TranslateMessage(&MyMsg);
DispatchMessage(&MyMsg);
}
UnMessageBreakAvoid;
return TRUE;
}
The first step create window,after that,use MessageBreakAvoid to bypass message breaking,The second paramenter of MessageBreakAvoid convert WM_KEYDOWN or WM_KEYUP to custom message,There is 1101,When set this,You try large number,otherwise collide with windows msg code.
Th third paramenter is be create oneself or not

Debug return:succeed to bypass OllyDbg's msg trace.

Friday, August 5, 2011

Hijacking kernel handle

Anthor:Sysnap
Why need handle?
Handle just use citing of object,This is simple for get object when entry kernel.But why need handle? We should speak to need handle for parameter call api.Because irect use object,Maybe involves many of not-export.if realize oneself that is hardly real.however,Use standard kernel api depend on handle in many cases and we can't get handle for a kinds of reason.We will discuss how get a useful handle.

1.Create Handle
ObpCreateHandle will diagnoseAccessMode,if there is user mode,PVOID ObjectTable;
ObjectTable = PsGetCurrentProcess()->ObjectTable
If there is driver to open handle,ObjectTable = ObpKernelHandleTable;
ObpKernelHandleTable is pointer of HANDLE_TABLE with not-export and ATTACH to process of SYSTEM at systerm.
Call ObpIncrementHandleCount to add Object count numbers,here notice without necessary to do some thing .
Call ExCreateHandle to create handle,Call in ExCreateHandle
//// Allocation one HANDLE_TABLE_ENTRY and a handle,The handle's value produce and finished on
///ExpAllocateHandleTableEntry.
ExpAllocateHandleTableEntry is core for allocation handle,That refer to related data structure.but leave it.
We only know ObpCreateHandle to return handle and add a HANDLE_TABLE_ENTRY at ObjectTable
lkd> dt _HANDLE_TABLE_ENTRY
nt!_HANDLE_TABLE_ENTRY
   +0x000 Object           : Ptr32 Void
HANDLE_TABLE_ENTRY Include our Object.


2 Handle to mapping of OBJECT
There refer to format of HandleTable,Online talk about HandleTable,Here don't talk about is
typedef struct _EXHANDLE    
{   
    union    
    {   
        struct    
        {   
            ULONG TagBits : 02;   
            ULONG Index   : 30;   
        };   
   
        HANDLE GenericHandleOverlay;   
    };   
   
} EXHANDLE, *PEXHANDLE;

It is observed that a type is for HANDLE.Infact that is divided into two parts-TagBits and Index,Specific what,watch next function
PHANDLE_TABLE_ENTRY    
    LookupHandleTableEntry(   
               IN PXP_HANDLE_TABLE HandleTable,   
               IN EXHANDLE         Handle   
               )   
{   
    ULONG i, j, k;   
    PHANDLE_TABLE_ENTRY Entry = NULL;   
    ULONG TableCode = HandleTable->TableCode& ~TABLE_LEVEL_MASK;   
   
    i = (Handle.Index >> 17) &0x1FF;   
    j = (Handle.Index >> 9)  &0x1FF;   
    k = (Handle.Index)       &0x1FF;   
   
    switch (HandleTable->TableCode &TABLE_LEVEL_MASK)   
    {   
        case 0 :   
          Entry = &((PHANDLE_TABLE_ENTRY)TableCode)[k];   
        break;   
           
        case 1 :   
          if (((PVOID *)TableCode)[j])    
          {   
             Entry = &((PHANDLE_TABLE_ENTRY *)TableCode)[j][k];            
          }   
        break;   
        case 2 :   
          if (((PVOID *)TableCode)[i])   
          if (((PVOID **)TableCode)[i][j])   
          {   
             Entry = &((PHANDLE_TABLE_ENTRY **)TableCode)[i][j][k];           

             
          }   
        break;   
    }   
    return Entry;   
}

We can get HANDLE_TABLE_ENTRY to get Object depanded on handle
Above function only fit XP and 2003

3.Permissions of handle
If we modified one permissions of handle to throughHANDLE_TABLE_ENTRY::GrantedAccess

4ObOpenObjectByPointer
ObReferenceObjectByPointer add count
ObpCreateHandle create handle

5.How fake
Such as we forge handle of XX.EXE process.

1 First need confirm ObpKernelHandleTable
  DWORD dwObpKernelHandleTable = 0;
  PVOID lpPsSystemObject = (PVOID)PsGetCurrentProcess();
  dwObpKernelHandleTable = *(DWORD*)((DWORD)lpPsSystemObject +

gdwObjectTableOffset);

2 ObOpenObjectByPointer open explorer.exe (Try to find protective process)
Get handle hProcess
3 Get EPROCESS of XX.EXE's process object with some way
4 hProcess as an paramenter to be call,LookupHandleTableEntry get pEntry that was pointer of PHANDLE_TABLE_ENTRY
It's about time pEntry->Object must is EPRCESS of explorer.exe
5 Modified pEntry->Object = XX.EXE的EPROCESS
This is the time we finishied HANDLE and OBJECT hijack..

There is key step and some detauks need notice,such as add handle count of object etc.


6 Have the effect?
We know most kernel API have a parament as HANDLE and inside most call it.
ObReferenceObjectByHandle position object,Analysis ObReferenceObjectByHandle we can know how hijack was useful.
It is clear ObReferenceObjectByHandle depend on HANDLE_TABLE to handle into object,That is handle--->> pEntry->Object
So hijack was successed.
That is my thiking,Thanks.
reference:
[1] WRK
[2] PsCidTable related to article

Thursday, August 4, 2011

My ollydbg download

This is modified ollydbg by me,Bypass VMP and Themida -- with strongOD.

Download:lypbook

Wednesday, August 3, 2011

Write a WPE

Author:taokla
I write tool of cut out packet and send packet at with WPE,Now I take out to share.
Download:http://filemarkets.com/file/newbing/b87f6040/

Tuesday, August 2, 2011

Programming of Asterisk Viewer

Author:qqaben
I download a software of Asterisk Viewer these two days,Software has ugly windows And farraginous performance,Let me not inthe mood to use, So I writed myself.I know to send WM_GETTEXT event for get window's text,do it:

code:
//控制台
    ..........
    while(1)
    {
      Sleep(1000);
      POINT Point;
      ::GetCursorPos(&Point);
      HWND m_hWnd=WindowFromPoint(Point);
      if(m_hWnd)
      {
        char szText[256];
        int iLength = SendMessage(m_hWnd,WM_GETTEXT,256,(LPARAM)szText);
        szText[iLength]='\0';
        {
          char szClassName[128];
          int iClassLength = GetClassName(m_hWnd,szClassName,128);
          szClassName[iClassLength] = '\0';
          printf("%s  ClassName:%s\n",szText,szClassName);
        }
      } 
    }
    .............
Watch the picture,We get right edit's text when moved to login(用户名),however,We can't get nothing on passwd edit.It seems some protection after edit seting up ES_PASSWD styles.Maybe don't use WM_GETTEXT,Wathch MSDN:

Displays an asterisk (*) for each character typed into the edit control. This style is valid only for singleline edit controls.

To change the characters that is displayed, or set or clear this style, use the EM_SETPASSWORDCHAR message.

Can I get passwd if password be sent EM_SETPASSWORDCHAR first,after be sent WM_GETTEXT ? Test it,I can't get yet.

Watch other people' software,OD loaded,bp GetWindowLong.

F9 run,Drag magnifier of soft,Stop there:

00401ABC  |> \6A F0         push    -10                           ; /Index = GWL_STYLE

  00401ABE  |.  FF75 10       push    dword ptr [ebp+10]            ; |hWnd
  00401AC1  |.  FF15 0C924000 call    dword ptr [<&USER32.GetWind>  ; \GetWindowLongA
  00401AC7  |.  8BD8          mov     ebx, eax
  00401AC9  |.  8D85 D8FCFFFF lea     eax, dword ptr [ebp-328]      ;  Stack Address =0012F87C, (ASCII "EDIT")
  00401ACF  |.  68 ECB14000   push    0040B1EC                      ;  ASCII "EDIT"
  00401AD4  |.  50            push    eax                           ;  可见在GetWindowLong前面已经调用过GetClassName
  00401AD5  |.  E8 361B0000   call    00403610                      ;  test window's type of magnifier and EDIT
  00401ADA  |.  59            pop     ecx
  00401ADB  |.  85C0          test    eax, eax
  00401ADD  |.  59            pop     ecx
  00401ADE  |.  0F84 CA000000 je      00401BAE                      ;   Edit, jump keyt
  ..........

  00401BAE  |> \F6C3 20       test    bl, 20
  00401BB1  |.  74 57         je      short 00401C0A
  00401BB3  |.  833D 4CE44000>cmp     dword ptr [40E44C], 0
  00401BBA  |.^ 74 D9         je      short 00401B95
  00401BBC  |.  8D45 14       lea     eax, dword ptr [ebp+14]
  00401BBF  |.  50            push    eax
  00401BC0  |.  FF75 10       push    dword ptr [ebp+10]            ;  可以用spy查看一下,此处存放的是密码框的句柄
  00401BC3  |.  FFD7          call    edi                           ;  USER32.GetWindowThreadProcessId
  00401BC5  |.  FF75 14       push    dword ptr [ebp+14]            ; /ProcessId
  00401BC8  |.  6A 00         push    0                             ; |Inheritable = FALSE
  00401BCA  |.  68 3A040000   push    43A                           ; |Access = CREATE_THREAD|VM_OPERATION|VM_READ|VM_WRITE|QUERY_INFORMATION
  00401BCF  |.  FF15 34904000 call    dword ptr [<&KERNEL32.OpenP>  ; \OpenProcess
  00401BD5  |.  8BF0          mov     esi, eax
  00401BD7  |.  85F6          test    esi, esi
  00401BD9  |.  74 1C         je      short 00401BF7
  00401BDB  |.  8D85 D8FEFFFF lea     eax, dword ptr [ebp-128]
  00401BE1  |.  50            push    eax
  00401BE2  |.  FF75 10       push    dword ptr [ebp+10]
  00401BE5  |.  56            push    esi
  00401BE6  |.  E8 01F6FFFF   call    004011EC                       ;  keyt
  00401BEB  |.  83C4 0C       add     esp, 0C
  00401BEE  |.  56            push    esi                            ; /hObject
  00401BEF  |.  FF15 38914000 call    dword ptr [<&KERNEL32.Close>   ; \CloseHandle
  00401BF5  |.  EB 13         jmp     short 00401C0A
  00401BF7  |>  8D85 D8FEFFFF lea     eax, dword ptr [ebp-128]
  00401BFD  |.  68 50E44000   push    0040E450
  00401C02  |.  50            push    eax
  00401C03  |.  E8 98130000   call    00402FA0
  00401C08  |.  59            pop     ecx
  00401C09  |.  59            pop     ecx
  00401C0A  |>  8D85 D8FEFFFF lea     eax, dword ptr [ebp-128]
  00401C10  |.  50            push    eax                            ; /Text
  00401C11  |.  68 EC030000   push    3EC                            ; |/ControlID = 3EC (1004.)
  00401C16  |.  FF75 08       push    dword ptr [ebp+8]              ; ||hWnd
  00401C19  |.  FF15 94914000 call    dword ptr [<&USER32.GetDlgI>   ; |\GetDlgItem
  00401C1F  |.  50            push    eax                            ; |hWnd
  00401C20  |.  FF15 10924000 call    dword ptr [<&USER32.SetWind>   ; \SetWindowTextA 

  run in call    004011EC

  004011EC  /$  6A 00         push    0
  004011EE  |.  FF7424 10     push    dword ptr [esp+10]
  004011F2  |.  FF7424 10     push    dword ptr [esp+10]           ;  Edit 的句柄, 就叫它 m_EditHwnd 吧
  004011F6  |.  FF7424 10     push    dword ptr [esp+10]           ;  调用OpenProcess后返回的进程句柄 ,先叫它 m_ThreadHandle
  004011FA  |.  E8 01FEFFFF   call    00401000                     ;  某个函数,形如:Function(var1,var2,var3,var4)
  004011FF  |.  83C4 10       add     esp, 10
  00401202  \.  C3            retn[/code] 
 再跟进call    00401000    
  00401000  /$  55            push    ebp
  00401001  |.  8BEC          mov     ebp, esp
  00401003  |.  6A FF         push    -1
  00401005  |.  68 38924000   push    00409238
  0040100A  |.  68 B0314000   push    004031B0                            ;  SE 处理程序安装
  0040100F  |.  64:A1 0000000>mov     eax, dword ptr fs:[0]
  00401015  |.  50            push    eax
  00401016  |.  64:8925 00000>mov     dword ptr fs:[0], esp
  0040101D  |.  81EC 30010000 sub     esp, 130
  00401023  |.  53            push    ebx
  00401024  |.  56            push    esi
  00401025  |.  57            push    edi
  00401026  |.  33F6          xor     esi, esi
  00401028  |.  8975 E4       mov     dword ptr [ebp-1C], esi
  0040102B  |.  8975 DC       mov     dword ptr [ebp-24], esi
  0040102E  |.  8975 D0       mov     dword ptr [ebp-30], esi
  00401031  |.  8975 E0       mov     dword ptr [ebp-20], esi
  00401034  |.  8975 FC       mov     dword ptr [ebp-4], esi
  00401037  |.  68 60B04000   push    0040B060                            ; /pModule = "user32"
  0040103C  |.  FF15 6C904000 call    dword ptr [<&KERNEL32.GetModuleHa>  ; \GetModuleHandleA
  00401042  |.  8945 CC       mov     dword ptr [ebp-34], eax
  00401045  |.  3BC6          cmp     eax, esi
  00401047  |.  0F84 17010000 je      00401164
  0040104D  |.  8B45 0C       mov     eax, dword ptr [ebp+C]
  00401050  |.  8985 C4FEFFFF mov     dword ptr [ebp-13C], eax
  00401056  |.  807D 14 00    cmp     byte ptr [ebp+14], 0
  0040105A  |.  B8 50B04000   mov     eax, 0040B050                       ;  ASCII "SendMessageW"
  0040105F  |.  75 05         jnz     short 00401066
  00401061  |.  B8 40B04000   mov     eax, 0040B040                       ;  ASCII "SendMessageA"
  00401066  |>  50            push    eax                                 ; /ProcNameOrOrdinal
  00401067  |.  FF75 CC       push    dword ptr [ebp-34]                  ; |hModule
  0040106A  |.  FF15 D8904000 call    dword ptr [<&KERNEL32.GetProcAddr>  ; \GetProcAddress
  00401070  |.  8985 C8FEFFFF mov     dword ptr [ebp-138], eax            ;  获取了SendMessage 函数的地址,保存好,一会要用到
  00401076  |.  6A 40         push    40
  00401078  |.  59            pop     ecx
  00401079  |.  33C0          xor     eax, eax
  0040107B  |.  8DBD CCFEFFFF lea     edi, dword ptr [ebp-134]
  00401081  |.  F3:AB         rep     stos dword ptr es:[edi]
  00401083  |.  39B5 C8FEFFFF cmp     dword ptr [ebp-138], esi
  00401089  |.  0F84 D5000000 je      00401164
  0040108F  |.  6A 04         push    4                                   ; /flProtect = 4
  00401091  |.  68 00100000   push    1000                                ; |flAllocationType = 1000 (4096.)
  00401096  |.  BF 08010000   mov     edi, 108                            ; |
  0040109B  |.  57            push    edi                                 ; |dwSize => 108 (264.)
  0040109C  |.  56            push    esi                                 ; |lpAddress
  0040109D  |.  FF75 08       push    dword ptr [ebp+8]                   ; |hProcess
  004010A0  |.  FF15 DC904000 call    dword ptr [<&KERNEL32.VirtualAllo>  ; \VirtualAllocEx
  004010A6  |.  8945 D8       mov     dword ptr [ebp-28], eax             ;

 在 m_ThreadHandle 的虚地址空间里分配一块空间 VirMem1, 108h字节

  004010A9  |.  3BC6          cmp     eax, esi
  004010AB  |.  0F84 B3000000 je      00401164
  004010B1  |.  8D4D E0       lea     ecx, dword ptr [ebp-20]
  004010B4  |.  51            push    ecx                                 ; /pBytesWritten
  004010B5  |.  57            push    edi                                 ; |BytesToWrite => 108 (264.)
  004010B6  |.  8D8D C4FEFFFF lea     ecx, dword ptr [ebp-13C]            ; |
  004010BC  |.  51            push    ecx                                 ; |Buffer = 0012F60C
  004010BD  |.  50            push    eax                                 ; |Address = D60000
  004010BE  |.  FF75 08       push    dword ptr [ebp+8]                   ; |hProcess = 00000088 (window)
  004010C1  |.  8B1D E0904000 mov     ebx, dword ptr [<&KERNEL32.WriteP>  ; |kernel32.WriteProcessMemory
  004010C7  |.  FFD3          call    ebx                                 ; \WriteProcessMemory

Start from buffer = 0012F60C,VirMem1 is be write something,follow buffer to point address on data window,We can find that 0008093E is handle of Edit and 772DF3B7 is SendMessage address.
Then look down:

  004010C9  |.  BE EB114000   mov     esi, 004011EB
  004010CE  |.  81EE CB114000 sub     esi, 004011CB
  004010D4  |.  89B5 C0FEFFFF mov     dword ptr [ebp-140], esi
  004010DA  |.  6A 40         push    40                                  ; /flProtect = 40 (64.)
  004010DC  |.  68 00100000   push    1000                                ; |flAllocationType = 1000 (4096.)
  004010E1  |.  56            push    esi                                 ; |dwSize => 20 (32.)
  004010E2  |.  6A 00         push    0                                   ; |lpAddress = NULL
  004010E4  |.  FF75 08       push    dword ptr [ebp+8]                   ; |hProcess = 00000088 (window)
  004010E7  |.  FF15 DC904000 call    dword ptr [<&KERNEL32.VirtualAllo>  ; \VirtualAllocEx

VirtualAlloc VirMem2,

  004010ED  |.  8945 D4       mov     dword ptr [ebp-2C], eax               ;  分配的内存地址: D70000
  004010F0  |.  85C0          test    eax, eax
  004010F2  |.  74 6E         je      short 00401162
  004010F4  |.  8D4D E0       lea     ecx, dword ptr [ebp-20]
  004010F7  |.  51            push    ecx                                   ; /pBytesWritten
  004010F8  |.  56            push    esi                                   ; |BytesToWrite => 20 (32.)
  004010F9  |.  68 CB114000   push    004011CB                              ; |Buffer = ViewPass.004011CB
  004010FE  |.  50            push    eax                                   ; |Address = D70000
  004010FF  |.  FF75 08       push    dword ptr [ebp+8]                     ; |hProcess = 00000088 (window)
  00401102  |.  FFD3          call    ebx                                   ; \WriteProcessMemory

Buffer = ViewPass.004011CB,Right menu select "Disassembly",show it:

  004011CB   .  56                    push    esi
  004011CC   .  8B7424 08             mov     esi, dword ptr [esp+8]
  004011D0   .  8D46 08               lea     eax, dword ptr [esi+8]
  004011D3   .  50                    push    eax
  004011D4   .  68 00010000           push    100
  004011D9   .  6A 0D                 push    0D
  004011DB   .  FF36                  push    dword ptr [esi]
  004011DD   .  FF56 04               call    dword ptr [esi+4]
  004011E0   .  80A6 07010000 00      and     byte ptr [esi+107], 0
  004011E7   .  5E                    pop     esi
  004011E8   .  C2 0400               retn    4

Next watch,Later analyse what to do.

  00401104  |.  8D45 DC       lea     eax, dword ptr [ebp-24]
  00401107  |.  50            push    eax                                   ; /lpThreadId
  00401108  |.  33F6          xor     esi, esi                              ; |
  0040110A  |.  56            push    esi                                   ; |dwCreationFlags => 0
  0040110B  |.  FF75 D8       push    dword ptr [ebp-28]                    ; |lpParameter => 00D60000
  0040110E  |.  FF75 D4       push    dword ptr [ebp-2C]                    ; |lpStartAddress = 00D70000
  00401111  |.  56            push    esi                                   ; |dwStackSize => 0
  00401112  |.  56            push    esi                                   ; |lpThreadAttributes => 0
  00401113  |.  FF75 08       push    dword ptr [ebp+8]                     ; |hProcess = 00000088 (window)
  00401116  |.  FF15 E4904000 call    dword ptr [<&KERNEL32.CreateRemoteT>  ; \CreateRemoteThread   

m_ThreadHandle create a process,m_ThreadHandle through OpenProcess to get when create password be create.lpStartAddress = 00D70000 The thread create to finished.Software will execute from here on.  lpParameter => 00D60000,That is transmitt parameter for the thread.

Analyse VirMem2 to write code.
  004011CB   .  56            push    esi           
  004011CC   .  8B7424 08     mov     esi, dword ptr [esp+8]       ;参数 00D60000   
  004011D0   .  8D46 08       lea     eax, dword ptr [esi+8]       ;00D60008,save passwd  
  004011D3   .  50            push    eax                          ;WM_GETTEXT get string address     
  004011D4   .  68 00010000   push    100                          ;最多返回100h个字符   
  004011D9   .  6A 0D         push    0D                           ;WM_GETTEXT   
  004011DB   .  FF36          push    dword ptr [esi]              ;Password's handle
  004011DD   .  FF56 04       call    dword ptr [esi+4]            ;SendMessage's address
  004011E0   .  80A6 07010000>and     byte ptr [esi+107], 0        ;'\0 '
  004011E7   .  5E            pop     esi
  004011E8   .  C2 0400       retn    4

Recalled the call doing:
1. push parameter
2. push return address
3. call interrupt
4. return from interrupt


New thread take as a function,Assume esp to point 00000018,Get the model.

    Stack         Content
    000010      push esi
    000014      return address
    000018      for thread transmit parameter 00D60000
    00001C 
    000020
    000024

Main analyse finished,Watch next:

  0040111C  |.  8945 E4       mov     dword ptr [ebp-1C], eax
  0040111F  |.  3BC6          cmp     eax, esi
  00401121  |.  74 3F         je      short 00401162
  00401123  |.  6A FF         push    -1                                    ; /Timeout = INFINITE
  00401125  |.  50            push    eax                                   ; |hObject = 00000098 (window)
  00401126  |.  FF15 EC904000 call    dword ptr [<&KERNEL32.WaitForSingle>  ; \WaitForSingleObject
 
  0040112C  |.  8D45 E0       lea     eax, dword ptr [ebp-20]
  0040112F  |.  50            push    eax                                   ; /pBytesRead
  00401130  |.  57            push    edi                                   ; |BytesToRead => 108 (264.)
  00401131  |.  8D85 C4FEFFFF lea     eax, dword ptr [ebp-13C]              ; |
  00401137  |.  50            push    eax                                   ; |Buffer = 0012F60C
  00401138  |.  FF75 D8       push    dword ptr [ebp-28]                    ; |pBaseAddress = D60000
  0040113B  |.  FF75 08       push    dword ptr [ebp+8]                     ; |hProcess = 00000088 (window)
  0040113E  |.  FF15 90904000 call    dword ptr [<&KERNEL32.ReadProcessMe>  ; \ReadProcessMemory

Get passwd finished.

Flow:
1.Get edit's handle.
2.GetWindowThreadProcessId() get to create edit's id.
3.OpenProcess(); Open the thread's object,Get the object's HANDLE;
4.Virtual memory at remote thread,write my code.
5.Create remote thread to create my code.
6.Return result.
7.Free momery.

Attach code:

code:
 //定义全局变量
  static BYTE RemoteCode[]=
  {
    "\x56\x8B\x74\x24\x08\x8D\x46\x08"

    "\x50\x68\x00\x01\x00\x00\x6A\x0D"

    "\xFF\x36\xFF\x56\x04\x80\xA6\x07"

    "\x01\x00\x00\x00\x5E\xC2\x04\x00"

  };

  struct Parameter{

    HWND    hWnd;

    FARPROC    pProc;

    DWORD    dwBuffer[128];

    Parameter()
    {

      hWnd  =0;

      pProc =0;

      memset(dwBuffer,0,sizeof(dwBuffer));

    }

  }; 

  Parameter RemoteParmeter;

code:
void CPWDLookDlg::GetPassWord(HWND hWnd)
{

    try{

      RemoteParmeter.hWnd = hWnd;

      DWORD  m_ThreadID = 0;

      GetWindowThreadProcessId(hWnd,&m_ThreadID);

      HANDLE  m_ThreadHandle = ::OpenProcess(0x43A,FALSE,m_ThreadID);

      if(!m_ThreadHandle)  { return; }

      HMODULE m_Usr32Mod = GetModuleHandle("user32");

      FARPROC m_SendMessageFun = GetProcAddress(m_Usr32Mod,"SendMessageA");

      RemoteParmeter.pProc = m_SendMessageFun;

      LPVOID  m_VirMem1 = VirtualAllocEx(m_ThreadHandle,NULL,sizeof(RemoteParmeter),MEM_COMMIT,PAGE_READWRITE);

      if(!m_VirMem1) { return; }

      if(!WriteProcessMemory(m_ThreadHandle,m_VirMem1, &RemoteParmeter,sizeof(RemoteParmeter),NULL)) {return;}

      LPVOID  m_VirMem2 = VirtualAllocEx(m_ThreadHandle,NULL,sizeof(RemoteCode),MEM_COMMIT,PAGE_EXECUTE_READWRITE);

      if(!m_VirMem2) { return; }

      if(!WriteProcessMemory(m_ThreadHandle,m_VirMem2, RemoteCode,sizeof(RemoteCode),NULL)){return;}

      HANDLE m_RemoteThreadHandle =
        CreateRemoteThread(m_ThreadHandle,NULL,NULL,(LPTHREAD_START_ROUTINE)m_VirMem2,m_VirMem1,NULL,NULL);

      if(!m_RemoteThreadHandle) { return; }

      WaitForSingleObject(m_RemoteThreadHandle,INFINITE);

      if(!ReadProcessMemory(m_ThreadHandle,m_VirMem1 ,&RemoteParmeter,sizeof(RemoteParmeter),NULL)) {return;}

      CString m_strPwd;

      m_strPwd.Format("%s",RemoteParmeter.dwBuffer);

      m_ediPWord.SetWindowText(m_strPwd);

      VirtualFreeEx(m_ThreadHandle,m_VirMem1,0,MEM_RELEASE);

      VirtualFreeEx(m_ThreadHandle,m_VirMem2,0,MEM_RELEASE);

      DWORD lpExitCode;

      GetExitCodeThread(m_RemoteThreadHandle ,&lpExitCode);

      CloseHandle(m_RemoteThreadHandle);

      CloseHandle(m_ThreadHandle);

    }catch(...)

    {
      AfxMessageBox("Error!");
    }

}

Monday, August 1, 2011

Law of ESP go into hiding:0x12FFC,Why it is?

Author:tnttools
Law of ESP: If Stack keep balance for compression shell execute before and after,Interrupt will break on push ebp(the first instruction of OEP) When breakpoint was on 12FFC0.Why not ESP is 0xFFFC,but 0x0FFC4 ? This is realize by source code of windows.

Window use functiong to create process to use :kernel32.dll!_CreateProcessInternalW -> … -> kernel32.dll!_BaseProcessStartThunk() -> kernel32.dll!_BaseProcessStart() -> EP

Enter _BaseProcessStartThunk(),Stack:
+ 0012FFFC   00000000                <- ESP

---------------------------------------------------------<code>
   _BaseProcessStartThunk@8 proc near
xor     ebp, ebp
push    eax
push    0
jmp     _BaseProcessStart@4 ; BaseProcessStart(x)
_BaseProcessStartThunk@8 endp
----------------------------------------------------------</code>

在执行完_BaseProcessStartThunk时,堆栈的状态为
+ 0012FFFC   00000000               
+ 0012FFF8   EAX
+ 0012FFF4   0x00000000             <- ESP
   
---------------------------------------------------------<code>
    _BaseProcessStart proc
push    0Ch
push    offset dword_7C816FE0
call    __SEH_prolog
and     [ebp+ms_exc.disabled], 0
push    4
lea     eax, [ebp+8]
push    eax
push    9
push    0FFFFFFFEh
call    ds:__imp__NtSetInformationThread@16 ; NtSetInformationThread(x,x,x,x)
call    dword ptr [ebp+8]
push    eax             ; dwExitCode
call    _ExitThread@4
nop
nop
nop
---------------------------------------------------------</code>

Finish BaseProcessStart(),Stack:
+ 0012FFFC   0x00000000
+ 0012FFF8   OldEAX -2-> EntryPoint By NtSetInformationThread()
+ 0012FFF4   reserved, inited to 0x00000000
+ 0012FFF0   OldEBP(0x00000000)    <-p- NowEBP
+ 0012FFEC   TryLevel, inited to 0xFFFFFFFF
+ 0012FFE8   ScopeTable
+ 0012FFE4   __except_handler3 in kernel32.dll
+ 0012FFE0   0xFFFFFFFF            <-p- fs:00h
+ 0012FFDC   ExceptionInfo, Parameter of UnhandledExceptionFilter()
+ 0012FFD8   OldESP(0x0012FFC8)
+ 0012FFD4   ExceptionCode, Parameter of kernel32.dll!ExitProcess
+ 0012FFD0   EBX(pPEB)
+ 0012FFCC   ESI
+ 0012FFC8   EDI                   <-p- OldESP
+ 0012FFC4   retaddr in kernel32.dll!_BaseProcessStartThunk
                                               <-p- NowESP
Attach:
    DWORD   SizeOfStackReserve;                         // 0x48-4b
    DWORD   SizeOfStackCommit;                          // 0x4c-4f
    DWORD   SizeOfHeapReserve;                          // 0x50-53
    DWORD   SizeOfHeapCommit;                           // 0x54-57
This is four region of IOH.

Committed submit two types of virtual memory.
Reserved explain this memory to be purposes and can's be allocation;Memory is already map to virtual memory segment with physics memory by Committed submit(also can be moved to disk cache files pagefile.sys ).Beacause Memory Segment of Stack and Heap increasing properties of size with program running,first off don't gobble up precious physics memory.When they exhausted to exception,windows memory manager allot a part again.

SizeOfStackReserve  Program reserve to be used for memory segment size of stack space at the beginning
SizeOfStackCommit   Program reserve to be used for memory segment size of stack space and physics memory mapping size is submint at the beginning
SizeOfHeapReserve  Program reserve memory segment size of stack space at the beginning
SizeOfHeapCommit   Program reserve to be used for memory segment size of stack space and physics memory mapping size is submint at the beginning