以子之矛,陷子之盾,何如?——使用ChakraCore来Fuzz NScript (2)

我在很早以前做了一个多进程的Fuzz程序,其实最终的实现很简单,就是类似一个使用socket互相通信的程序,好似QQ互相发送消息一样。Server和Client约定好一组消息,互相通信。

代码实现很简单,百度随便一搜就是一大堆,比如:http://blog.csdn.net/yaopeng_2005/article/details/6696105,可以直接拿来用。NScript处,因为我需要将待分析的代码传给rs函数,在我没有传递完成前,整个流程都可以停滞。因此NScript作为客户端,只需要一直等待Server传来的Fuzz代码,并从Buffer中取出代码,传递给rs即可。

nscript.png

callClient.cpp

// callClient.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdio.h>  
#include <Winsock2.h>  

#pragma comment(lib, "ws2_32.lib")   


void main()  
{  
    WORD wVersionRequested = MAKEWORD(1, 1);   
    WSADATA wsaData;  
    int err = WSAStartup(wVersionRequested, &wsaData);

    if (err != 0) 
    {  
        return;  
    }  

    if (LOBYTE(wsaData.wVersion ) != 1 || HIBYTE(wsaData.wVersion) != 1) 
    {   
        WSACleanup();  
        return;  
    }  

    for (int index = 0; ; index++)  
    {  
        SOCKET sockClient = socket(AF_INET,SOCK_DGRAM, 0);  

        int len = sizeof(SOCKADDR);  

        SOCKADDR_IN local;  
        local.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");   
        local.sin_family = AF_INET;   
        local.sin_port = htons(27015);   

        DWORD dwSize = MAX_PATH;
        char sendBuf[MAX_PATH] = { 0 };  
        sprintf(sendBuf, "%3d,", index); 

        //client(ChakraCore) shall send a file name to client. incase of buffer has a limit of 64kb.
        strcat(sendBuf, "c:\\test\\wow.js"); 
        sendto(sockClient, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&local, len);  

        /*char recvBuf[50];  
        recvfrom(sockClient,recvBuf,50,0,(SOCKADDR*)&local,&len);  
        printf("my reply is : %s\n",recvBuf);  
        printf("%s\n",inet_ntoa(local.sin_addr));  
        */

        closesocket(sockClient);  
        Sleep(2000);       
        WSACleanup();  
    }  
}  

callServer.cpp

// callServer.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdio.h>  
#include <Winsock2.h>  

#pragma comment(lib, "ws2_32.lib")   

void main()  
{  
    WORD wVersionRequested = MAKEWORD(1, 1);
    WSADATA wsaData;  
    int err = WSAStartup(wVersionRequested, &wsaData);  

    if (err != 0) {  
        return;  
    }  

    if ( LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {   
        WSACleanup();  
        return;  
    }  

    SOCKET sockSrv = socket(AF_INET,SOCK_DGRAM, 0);  

    int len = sizeof(SOCKADDR);  

    SOCKADDR_IN from;     
    SOCKADDR_IN local;   
    local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);   
    local.sin_family = AF_INET;   
    local.sin_port = htons(27015);   

    int bindResult = bind(sockSrv, (SOCKADDR*)&local, len);  
    while(1)  
    {  
        DWORD dwSize = MAX_PATH;
        char recvBuf[MAX_PATH];  

        //server(NScript) will receive a buffer contains filename of generated fuzzer.

        recvfrom(sockSrv, recvBuf, dwSize, 0, (SOCKADDR*)&from, &len);

        printf("%s\n", recvBuf);  
        printf("%s\n", inet_ntoa(local.sin_addr));  

        /*char sendBuf[50];  
        sprintf(sendBuf, "Welcome %s to here!", inet_ntoa(from.sin_addr));    
        sendto(sockSrv, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&from, len);  
        */

        Sleep(2000);  
    }  
    closesocket(sockSrv);  

    WSACleanup();  
}  

而Client端如果发生异常,处理起来就更容易了,使用SetUnhandledExceptionFilter可以设置TopLevelExceptionFilter。这是一个定义为

LONG WINAPI UnhandledExceptionFilter(__in struct _EXCEPTION_POINTERS* pExceptionInfo)

的函数,可以在pExceptionInfo中取到异常信息并记录。

所以,这里的实现比较容易,
1、在NScript侧,WinMain进入时,调用
SetUnhandledExceptionFilter()

int WinMain(...)
{
    ...
    LPTOP_LEVEL_EXCEPTION_FILTER originalFilter = SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
    ...
}

2、MyUnhandledExceptionFilter里面可以收集异常信息并告警

LONG WINAPI MyUnhandledExceptionFilter(__in struct _EXCEPTION_POINTERS* pExcepInfo)
{
    DWORD dwCrashPid = GetCurrentProcessId();
    DWORD dwCrashTid = GetCurrentThreadId();

    pExcepInfo->ExceptionRecord.ExceptionCode;
    pExcepInfo->ExceptionRecord.ExceptionAddress;

    alert!
    ...

}

3、NScript部分,循环等待,并在接受到数据时调用__rs

4、ChakraCore部分

JsValueRef __stdcall WScriptJsrt::EchoCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
{
    for (unsigned int i = 1; i < argumentCount; i++)
    {
        ……
                if (i > 1)
                {
                    wprintf(_u(" "));
                }

                ////////////////////////////////////////////////////////
                SEND CODE HERE
                ////////////////////////////////////////////////////////

                wprintf(_u("%ls"), str.GetWideString());
            }
        }

        ……
    }
……

标签:none

添加新评论

captcha
请输入验证码