注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

mie

 
 
 

日志

 
 

【失败的尝试】ShellCode远程线程注入的安全扫描  

2012-04-05 22:15:09|  分类: 安全/ |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

针对某特定攻击方式,试图通过线程扫描方式,捕获注入的ShellCode,但是,却以失败而告终。

 

数据结构:

//可疑二进制数据信息的默认长度
#define ShellCodeInfoBinaryData_SIZE                        (50)

//可疑二进制数据信息
typedef struct tagShellCodeInfoBinaryData
{
    enumShellCodeInfoBinaryDataType dwExceptionType;        //异常特征类型(1:线程)
    DWORD dwInitialAddr;                                //可疑内存区的起始地址
    DWORD dwOffset;                                        //可疑内存区的段起始偏移
    DWORD dwEntryAddr;                                    //可疑内存区的入口调用地址
    enumShellCodeInfoBinaryDataSource dwSource;            //数据来源
    BYTE  btBinaryData[ShellCodeInfoBinaryData_SIZE];        //附加二进制数据
    BYTE  reversed[2];
    DWORD dwVirtualSize;                                //内存区域大小(估算)
}ShellCodeInfoBinaryData, * LPShellCodeInfoBinaryData;

扫描代码:
    list<DWORD> thread_list;
    INT ret=g_EnumProcessThreads_ByToolHelp32(thread_list, GetCurrentProcessId());
    if (ret<0)
    {
        return -1;
    }

    ShellCodeInfoBinaryData data;
    list<DWORD>::iterator piter;
    for (piter=thread_list.begin(); piter!=thread_list.end(); piter++)
    {
        if(!IsThreadSafety(GetCurrentProcess(), *piter, &data))
        {
            break;
        }
    }

    if (piter==thread_list.end())
    {
        //安全
        return 0;
    }

功能函数:

//ToolHelp32方式枚举线程
INT g_EnumProcessThreads_ByToolHelp32(list<DWORD> & li, DWORD pid)
{
    li.clear();
    HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
    THREADENTRY32 te32={0};

    // Take a snapshot of all running threads 
    hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, pid );
    if( hThreadSnap == INVALID_HANDLE_VALUE )
    {
        return( -1 );
    }

    // Fill in the size of the structure before using it.
    te32.dwSize = sizeof(THREADENTRY32 );

    // Retrieve information about the first thread,
    // and exit if unsuccessful
    if( !Thread32First( hThreadSnap, &te32 ) )
    {
        CloseHandle( hThreadSnap );    // Must clean up the

        return( -1 );
    }

    // Now walk the thread list of the system,
    // and display information about each thread
    // associated with the specified process
    do
    {
        if( te32.th32OwnerProcessID == pid )
        {
            li.push_back(te32.th32ThreadID);
        }
    } while( Thread32Next(hThreadSnap, &te32 ) );

    CloseHandle( hThreadSnap );
    return( 0 );
}

//线程安全检测
BOOL IsThreadSafety(HANDLE hProcess, DWORD thread_id, ShellCodeInfoBinaryData * pShellCodeInfoBinaryData)
{
    if (thread_id==GetCurrentThreadId())
    {
        return TRUE;
    }

    HANDLE hThread=OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
    if (hThread==NULL)
    {
        return FALSE;
    }

    PVOID start_address=NULL;
    ULONG len=sizeof(PVOID);
    NTSTATUS status=STATUS_SUCCESS;
    status=NtQueryInformationThread(hThread, ThreadQuerySetWin32StartAddress, &start_address, len, &len);
    if (FAILED(status))
    {
        CloseHandle( hThread );

        return FALSE;
    }

    CloseHandle( hThread );

    //线程安全检测
    if(start_address==NULL)
    {
        return FALSE;
    }

    MEMORY_BASIC_INFORMATION memBI;

    if(VirtualQueryEx(hProcess, (LPVOID)start_address, &memBI, sizeof(memBI))==0)
    {
        return FALSE;
    }

    if (MEM_IMAGE!=memBI.Type)
    {
        memset(pShellCodeInfoBinaryData, 0, sizeof(ShellCodeInfoBinaryData));
        pShellCodeInfoBinaryData->dwEntryAddr=(DWORD)start_address;
        pShellCodeInfoBinaryData->dwExceptionType=1;
        pShellCodeInfoBinaryData->dwSource=1;
        pShellCodeInfoBinaryData->dwInitialAddr=(DWORD)memBI.AllocationBase;
        pShellCodeInfoBinaryData->dwOffset=pShellCodeInfoBinaryData->dwEntryAddr-pShellCodeInfoBinaryData->dwInitialAddr;

        INT size=sizeof(pShellCodeInfoBinaryData->btBinaryData);
        INT size2=(DWORD)memBI.BaseAddress+memBI.RegionSize-pShellCodeInfoBinaryData->dwEntryAddr;
        INT csize=min(size, size2);
        if (csize>0)
        {
            try
            {
                memcpy(pShellCodeInfoBinaryData->btBinaryData, start_address, csize);
            }
            catch (...)
            {
            }
        }

        pShellCodeInfoBinaryData->dwVirtualSize=memBI.RegionSize+pShellCodeInfoBinaryData->dwOffset/0x1000*0x1000;

        return FALSE;
    }

    return TRUE;
}

以上代码会导致堆栈溢出。初步推测是NtQueryInformationThread在XP系统下的调用,存在一定风险(ULONG len=sizeof(PVOID) 之后,给NtQueryInformationThread传递参数的时候,可能有点问题)。此外,OpenThread之后,线程可能刚好退出了(悲惨的局面,也许只能先锁定线程)。

 

By: 章永辉

  评论这张
 
阅读(925)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2016