songzihui 发表于 2013-3-27 10:11:42

让别人不能CALL我们的那些函数

这个话题,主要是因为跟朋友讨论一些小技术时,引发出来的,于是做了点笔记,不敢独享,故而发出来。
从线程入手就行了,不去使用可以被驱动拦截和监控的ZwSetInfomationThread和ZwQueryInformationThread而使用只操作用户层内存的三个函数:
RtlPushFrame
RtlGetFrame
RtlPopFrame
完全定义形态:
typedefVOID (NTAPI *T_RtlPushFrame)(
PTEB_ACTIVE_FRAME Frame
);
typedef PTEB_ACTIVE_FRAME (NTAPI *T_RtlGetFrame)(
VOID
);

typedef VOID (NTAPI *T_RtlPopFrame)(
PTEB_ACTIVE_FRAME Frame
);


其中PTEB_ACTIVE_FRAME的定义(通过windbg可以获得):
typedef struct TEB_ACTIVE_FRAME_CONTEXT
{
/* 0x000 */ ULONG   Flags;
/* 0x004 */ PSTR    FrameName;

} TEB_ACTIVE_FRAME_CONTEXT, *PTEB_ACTIVE_FRAME_CONTEXT;

typedef struct TEB_ACTIVE_FRAME
{
/* 0x000 */ ULONG                     Context;// Flags;
/* 0x004 */ struct TEB_ACTIVE_FRAME    *Previous;
/* 0x008 */ PTEB_ACTIVE_FRAME_CONTEXT   pContext;
} TEB_ACTIVE_FRAME, *PTEB_ACTIVE_FRAME;


具体的封装应用的逻辑:
一个自己的创建线程的封装(自己的线程除了系统给的第一个之外都是自己建立的)。
一个通用的检测函数,在某些关键函数(比如发包前的加密的函数,某个重要操作的函数)里加入调用检测函数(当然要适当使用VMP这类高强度的壳的SDK保护好自己的这套逻辑才好)。
封装一个设置给主线程和某些不明线程的使用的设置标识的函数。
封装一个用于清理的函数。


详情参看如下代码:

首先是头文件部分:
#pragma once
#include <windows.h>
#include <winternl.h>
#include <ntstatus.h>
typedef struct TEB_ACTIVE_FRAME_CONTEXT
{
/* 0x000 */ ULONG   Flags;
/* 0x004 */ PSTR    FrameName;

} TEB_ACTIVE_FRAME_CONTEXT, *PTEB_ACTIVE_FRAME_CONTEXT;

typedef struct TEB_ACTIVE_FRAME
{
/* 0x000 */ ULONG                     Context;// Flags;
/* 0x004 */ struct TEB_ACTIVE_FRAME    *Previous;
/* 0x008 */PTEB_ACTIVE_FRAME_CONTEXT   pContext;
} TEB_ACTIVE_FRAME, *PTEB_ACTIVE_FRAME;
typedef struct _THREADPARAM_
{
PVOID Context;
LPTHREAD_START_ROUTINE Routine;
}THREADPARAM,*PTHREADPARAM;
struct _OWN_THREAD_CONTEXT_ : public TEB_ACTIVE_FRAME
{
DWORD dwThreadId;
struct _OWN_THREAD_CONTEXT_ *Own;
};
typedefVOID (NTAPI *T_RtlPushFrame)(
PTEB_ACTIVE_FRAME Frame
);
typedef PTEB_ACTIVE_FRAME (NTAPI *T_RtlGetFrame)(
VOID
);

typedef VOID (NTAPI *T_RtlPopFrame)(
PTEB_ACTIVE_FRAME Frame
);
#define OWN_THREAD_FLAGS ULONG('MJMJ')
VOID SetOwnThread();//设置当前线程标志
BOOL IsOwnThread();//检测当前线程是否有标志,无标志返回FALSE有返回TRUE
VOID CleanUpOwnThread();//对当前线程清空标志
BOOL _CreateThreadEx(LPTHREAD_START_ROUTINE lpThreadRoutine,LPVOID lparam,PHANDLE pThreadHandle,PDWORD pThreadId);//创建新线程封装函数


接着实现逻辑的函数代码:

代码:
T_RtlPushFrame fRtlPushFrame=NULL;
T_RtlGetFrame fRtlGetFrame=NULL;
T_RtlPopFrame fRtlPopFrame=NULL;
#define OWN_THREAD_FLAGS ULONG('MJMJ')
BOOL InitOwnThread()
{
HMODULE hNtdll = GetModuleHandle(TEXT("ntdll.dll"));
if (!fRtlGetFrame)
{
    if(!(fRtlGetFrame = (T_RtlGetFrame)GetProcAddress(hNtdll,"RtlGetFrame"))) return FALSE;
}
if (!fRtlPopFrame)
{
    if(!(fRtlPopFrame = (T_RtlPopFrame)GetProcAddress(hNtdll,"RtlPopFrame"))) return FALSE;
}
if (!fRtlPushFrame)
{
    if(!(pRtlPushFrame = (T_RtlPushFrame)GetProcAddress(hNtdll,"RtlPushFrame"))) return FALSE;
}
return TRUE;
}
VOID SetOwnThread()
{
_OWN_THREAD_CONTEXT_ *pContext = new _OWN_THREAD_CONTEXT_;
if (pContext)
{
    RtlZeroMemory(pContext,sizeof(_OWN_THREAD_CONTEXT_));
    pContext->Context = OWN_THREAD_FLAGS;
    pContext->dwThreadId = GetCurrentThreadId();
    pContext->Own = pContext;
    fRtlPushFrame(pContext);
}
}
VOID CleanUpOwnThread()
{
PTEB_ACTIVE_FRAME Frame;
if (!InitOwnThread())
{
    return ;
}
Frame = fRtlGetFrame();
while (Frame != NULL && Frame->Context != OWN_THREAD_FLAGS)
    Frame = Frame->Previous;
if (Frame)
{
    _OWN_THREAD_CONTEXT_ *pCtx = (_OWN_THREAD_CONTEXT_ *)Frame;
    pCtx = pCtx->Own;
    fRtlPopFrame(Frame);
    delete pCtx;
}
return ;
}
DWORD WINAPI _ThreadRoutineEx(LPVOID lparam)
{
DWORD dwRet= 0;
PTHREADPARAM pThread;
SetOwnThread();
pThread = (PTHREADPARAM)lparam;
if (pThread&&pThread->Routine)
{
   dwRet = pThread->Routine(pThread->Context);
}
CleanUpOwnThread();
return dwRet;
}

BOOL _CreateThreadEx(LPTHREAD_START_ROUTINE lpThreadRoutine,LPVOID lparam,PHANDLE pThreadHandle,PDWORD pThreadId)
{
HANDLE hThread;
PTHREADPARAM threadparam;
if (!InitOwnThread())
{
    return FALSE;
}
threadparam = new THREADPARAM;
if (threadparam)
{
    RtlZeroMemory(threadparam,sizeof(THREADPARAM));
    threadparam->Routine = lpThreadRoutine;
    threadparam->Context = lparam;
    hThread = CreateThread(NULL,0,_ThreadRoutineEx,threadparam,0,pThreadId);
    if (pThreadHandle)
    {
      *pThreadHandle = hThread;
    }
    if (hThread)
    {
      return TRUE;
    }
}
return FALSE;
}
BOOL IsOwnThread()
{
PTEB_ACTIVE_FRAME Frame;
if (!InitOwnThread())
{
    return FALSE;
}
Frame = fRtlGetFrame();
while (Frame != NULL && Frame->Context != OWN_THREAD_FLAGS)
    Frame = Frame->Previous;
if (Frame)
{
    _OWN_THREAD_CONTEXT_ *pContext = (_OWN_THREAD_CONTEXT_ *)Frame;
    if (pContext->dwThreadId==GetCurrentThreadId())
    {
      return TRUE;
    }
}
return FALSE;
}
页: [1]
查看完整版本: 让别人不能CALL我们的那些函数