易语言核心runtime的loader和部分services的逆向工程

下面的代码易语言核心runtime(核心支持库krnln.fne)的易格式loader和部分核心services的逆向工程分析。仅仅是逆向分析而已,代码没有经过任何优化。其他就没什么好说的了,具体就看代码吧。

注:和E-Code Explorer配合使用会有意想不到的效果:)


////////////////////////////////////////////////////////////
////    MicroLoader v0.01
////    filename:    MicroLoader.cpp
////    coder:    monkeycz
////    create time:  2005/09/29 23:21
////    fix time:    2005/10/21
////////////////////////////////////////////////////////////


#include "MicroLoader.h"

PIMAGE_DOS_HEADER DosHeader = NULL; 
PIMAGE_NT_HEADERS NtHeader = NULL;
PIMAGE_SECTION_HEADER SectionHeader = NULL;
PAPP_HEADER_INFO ECodeHeaderInfo = NULL;
PSECTION_INFO ThisSectionInfo = NULL;
PRELOCATION_INF ThisRelocationInfo = NULL;
UINT32 NumberOfSections = 0;
UINT32 ESectionVA = 0;
char SectionName[IMAGE_SIZEOF_SHORT_NAME + 1];
UINT32 ServerPointTable[ESERVERCOUNT];

typedef void (__stdcall* ECODESTART)(void);
ECODESTART ECodeStart = NULL;

PFN_GET_LIB_INFO GetThisNewInfo = NULL;

PSECTION_INFO pConstSectionOffset = NULL;
PSECTION_INFO pWinFormSectionOffset = NULL;
PSECTION_INFO pHelpFuncSectionOffset = NULL;
PSECTION_INFO pCodeSectionOffset = NULL;
PSECTION_INFO pVarSectionOffset = NULL;

PDLLCMD DllCmdHead = NULL;
PDLLCMD ThisDllCmd = NULL;
UINT32 DllCmdNO = 0;

PLIBINFO LibInfoHead = NULL;
PLIBINFO ThisLibInfo = NULL;
LIBSTRINGINFO ThisLibStringInfo;
UINT32 LibCount = 0;

UINT32 SaveAAddress = 0;

typedef void (__stdcall* UNKNOWFUN)(void);
UNKNOWFUN UnKnowFun = NULL; 
HMODULE ThisLibrary = NULL;

HANDLE ThisHeap = NULL;

char* LibStringHead = NULL;
char* ThisLibString = NULL;

char ThisLibFileName[256];

PFN_EXECUTE_CMD** ThisCmdsFuncHead = NULL;
UINT32 LibCmdNO = 0;

PFN_NOTIFY_SYS MyNotifySys = NULL;
PFN_NOTIFY_LIB ThisNotifyLib = NULL;

char* ThisCmdLine = NULL;

char FileName_Full[256];
char FileName_Name[256];
char FileName_Path[256];

typedef void (__stdcall* GETNEWSOCK)(UINT32 Param1);
GETNEWSOCK GetNewSock = NULL; 

char ErrorString[256];

INT ThisBaseCmdOffset = -1;
PFN_EXECUTE_CMD* ThisExecuteCmdPoint = NULL;

//定义临时变量
UINT32 i = 0;
UINT32 temp = 0;
UINT32* ptemp = NULL;
bool FindOK = false;

//声明函数
void Exit(void);
void _cdecl ServerFunction_09(UINT32 Param1);
UINT32 _cdecl ServerFunction_06(UINT32 Param1);

//实现核心基本命令
void _cdecl bnot (PMDATA_INF pRetData, INT nArgCount, PMDATA_INF pArgInf)
{
  pRetData->m_int = ~(pArgInf->m_int);
  pRetData->m_dtDataType = SDT_INT;
  return;
}

void _cdecl band (PMDATA_INF pRetData, INT nArgCount, PMDATA_INF pArgInf)
{
  INT result = 0;
  result = pArgInf->m_int;
  for(int i = 1; i <= (nArgCount - 1); i++)
  {
    result = result & (pArgInf + i)->m_int;
  }
  pRetData->m_int = result;
  pRetData->m_dtDataType = SDT_INT;
  return;
}

void _cdecl bor (PMDATA_INF pRetData, INT nArgCount, PMDATA_INF pArgInf)
{
  INT result = 0;
  result = pArgInf->m_int;
  for(int i = 1; i <= (nArgCount - 1); i++)
  {
    result = result | (pArgInf + i)->m_int;
  }
  pRetData->m_int = result;
  pRetData->m_dtDataType = SDT_INT;
  return;
}

void _cdecl bxor (PMDATA_INF pRetData, INT nArgCount, PMDATA_INF pArgInf)
{
  INT result = 0;
  result = pArgInf->m_int;
  for(int i = 1; i <= (nArgCount - 1); i++)
  {
    result = result ^ (pArgInf + i)->m_int;
  }
  pRetData->m_int = result;
  pRetData->m_dtDataType = SDT_INT;
  return;
}

void _cdecl shl (PMDATA_INF pRetData, INT nArgCount, PMDATA_INF pArgInf)
{
  pRetData->m_int = pArgInf->m_int << (pArgInf + 1)->m_int;
  pRetData->m_dtDataType = SDT_INT;
  return;
}

void _cdecl shr (PMDATA_INF pRetData, INT nArgCount, PMDATA_INF pArgInf)
{
  pRetData->m_int = pArgInf->m_int >> (pArgInf + 1)->m_int;
  pRetData->m_dtDataType = SDT_INT;
  return;
}

void _cdecl pstr (PMDATA_INF pRetData, INT nArgCount, PMDATA_INF pArgInf)
{
  char* ThisStr = NULL, *NewStr = NULL;
  UINT32 ThisStrLen = 0;
  
  ThisStr = (char*)pArgInf->m_int;

  try
  {
    ThisStrLen = strlen(ThisStr);
  }
  catch(...)
  {
    MessageBoxA(0, ERROR_021, "error", MB_ICONERROR);
    ServerFunction_09(0);
    return;
  }

  if(ThisStrLen != 0)
  {
    NewStr = (char *)ServerFunction_06(ThisStrLen + 1);

    memcpy(NewStr, ThisStr, ThisStrLen + 1);
  }
  else
  {
    NewStr = NULL;
  }
    
  pRetData->m_pText = NewStr;
  pRetData->m_dtDataType = SDT_TEXT;
  return;
}

void _cdecl pbin (PMDATA_INF pRetData, INT nArgCount, PMDATA_INF pArgInf)
{
  unsigned char* ThisBin = NULL, *NewBin = NULL;
  UINT32 ThisBinLen = 0, *NewBinHead = NULL;

  ThisBin = (unsigned char*)pArgInf->m_int;
  ThisBinLen = (UINT32)(pArgInf++)->m_int;

  if(ThisBinLen != 0)
  {
    NewBin = (unsigned char *)ServerFunction_06(ThisBinLen + 8);
    NewBinHead = (UINT32*)NewBin;

    memcpy(NewBin + 8, ThisBin, ThisBinLen);
    
    (*NewBinHead) = 0x0001;
    (*(NewBinHead++)) = ThisBinLen;
  }
  else
  {
    NewBin = NULL;
  }

  pRetData->m_pBin = NewBin;
  pRetData->m_dtDataType = SDT_BIN;  
  return;
}


//核心代码从这里开始:)

void Exit(void)
{
  if(DllCmdHead != NULL)
  {
    free(DllCmdHead);
  }
  
  if(LibInfoHead != NULL)
  {
    ThisLibInfo = LibInfoHead;
    for(UINT32 i = 1; i <= LibCount; i++)
    {
      if(ThisLibInfo->ThisLibHandle == NULL || ThisLibInfo->ThisLibInfo == NULL)
      {
        continue;
      }
      
      ThisNotifyLib = ThisLibInfo->ThisLibInfo->m_pfnNotify;
      if(ThisNotifyLib != NULL)
      {
        ThisNotifyLib(NL_FREE_LIB_DATA, 0, 0);
      }
      
      FreeLibrary(ThisLibInfo->ThisLibHandle);
      ThisLibInfo->ThisLibHandle = NULL;
      ThisLibInfo->ThisLibInfo = NULL;

      ThisLibInfo++;
    }
    
    free(LibInfoHead);
  }
  
  if(ThisHeap != NULL)
  {
    HeapDestroy(ThisHeap);
  }

}

__declspec(naked) void _cdecl ServerFunction_09(UINT32 Param1)
{
  __asm
  {
    push ebp
    mov ebp, esp
  }

  if(SaveAAddress != NULL)
  {
    UnKnowFun = (UNKNOWFUN)SaveAAddress;
    UnKnowFun();
  }

  Exit();
  
  ExitProcess(Param1);  
  
  __asm
  {
    ret
  }
}

INT WINAPI ThisNotifySys(INT nMsg, DWORD dwParam1 = 0, DWORD dwParam2 = 0)
{
  PMDATA_INF ThisDataInfo = NULL;
  void* temppoint= NULL;
  DWORD temp = 0;

  switch(nMsg)
  {
    case NAS_GET_APP_ICON:
      //通知系统创建并返回程序的图标
      //和窗口组建相关,不处理
      sprintf(ErrorString, "%s\n\nIntra error number is %d.", ERROR_016, NAS_GET_APP_ICON);
      MessageBoxA(0, ErrorString, "error", MB_ICONERROR);
      ServerFunction_09(0);      
      break;
    case NAS_GET_LIB_DATA_TYPE_INFO:
      //返回指定库定义数据类型的PLIB_DATA_TYPE_INFO定义信息指针
      temp = dwParam1;
      if((temp >> 30) == 0)
      {
        ThisLibInfo = LibInfoHead;
        ThisLibInfo += ((temp >> 16) - 1);
        return (INT)(ThisLibInfo->ThisLibInfo->m_pDataType + (((temp << 16) >> 16) - 1));
      }
      break;
    case NAS_GET_HBITMAP:
      //返回非NULL的HBITMAP句柄(注意使用完毕后释放),否则返回NULL
      //和窗口组建相关,不处理
      sprintf(ErrorString, "%s\n\nIntra error number is %d.", ERROR_016, NAS_GET_HBITMAP);
      MessageBoxA(0, ErrorString, "error", MB_ICONERROR);
      ServerFunction_09(0);      
      break;
    case NAS_GET_LANG_ID:
      //返回当前系统或运行环境所支持的语言ID
      return 1;
    case NAS_GET_VER:
      //返回当前系统或运行环境的版本号
      return 0x00000004;
    case NAS_GET_PATH:
      //返回当前开发或运行环境的某一类目录或文件名,目录名以“\”结束
      switch(dwParam1)
      {
        case 1:
          strcpy((char*)dwParam2, FileName_Path);
          return (INT)FileName_Path;
          break;
        case 2001:
          strcpy((char*)dwParam2, FileName_Path);
          return (INT)FileName_Path;
          break;
        case 2002:
          strcpy((char*)dwParam2, FileName_Name);
          return (INT)FileName_Name;
          break;
        default:
          return NULL;    
      }
    case NRS_UNIT_DESTROIED:
      //通知系统指定的单元已经被销毁。
      //和窗口组建相关,不处理。
      sprintf(ErrorString, "%s\n\nIntra error number is %d.", ERROR_016, NRS_UNIT_DESTROIED);
      MessageBoxA(0, ErrorString, "error", MB_ICONERROR);
      ServerFunction_09(0);
      break;
    case NRS_CONVERT_NUM_TO_INT:
      //转换其它数值格式到整数
      ThisDataInfo = (PMDATA_INF)dwParam1;
      switch(ThisDataInfo->m_dtDataType)
      {
        case SDT_SHORT:
          return (int)(ThisDataInfo->m_short);
        case SDT_INT:
          return (int)(ThisDataInfo->m_int);
        case SDT_INT64:
          return (int)(ThisDataInfo->m_int64);
        case SDT_FLOAT:
          return (int)(ThisDataInfo->m_float);
        case SDT_DOUBLE:
          return (int)(ThisDataInfo->m_double);
        default:
          return 0;
      }
      break;
    case NRS_GET_CMD_LINE_STR:
      //取当前命令行文本
      return (INT)ThisCmdLine;
    case NRS_GET_EXE_PATH_STR:
      //取当前执行文件所处目录名称
      return (INT)FileName_Path;
    case NRS_GET_EXE_NAME:
      //取当前执行文件名称
      return (INT)FileName_Name;
    case NRS_GET_UNIT_PTR:
      //取单元对象指针
      //和窗口组建相关,不处理
      sprintf(ErrorString, "%s\n\nIntra error number is %d.", ERROR_016, NRS_GET_UNIT_PTR);
      MessageBoxA(0, ErrorString, "error", MB_ICONERROR);
      ServerFunction_09(0);
      break;
    case NRS_GET_AND_CHECK_UNIT_PTR:
      //取单元对象指针
      //和窗口组建相关,不处理
      sprintf(ErrorString, "%s\n\nIntra error number is %d.", ERROR_016, NRS_GET_AND_CHECK_UNIT_PTR);
      MessageBoxA(0, ErrorString, "error", MB_ICONERROR);
      ServerFunction_09(0);
      break;
    case NRS_EVENT_NOTIFY:
      //通知系统产生了事件
      //和窗口组建相关,不处理
      sprintf(ErrorString, "%s\n\nIntra error number is %d.", ERROR_016, NRS_EVENT_NOTIFY);
      MessageBoxA(0, ErrorString, "error", MB_ICONERROR);
      ServerFunction_09(0);
      break;
    /*
    在新版本的支持库中不支持
    case NRS_STOP_PROCESS_EVENT_NOTIFY:
      //通知系统暂停处理事件通知
      //和窗口组建相关,不处理
      sprintf(ErrorString, "%s\n\nIntra error number is %d.", ERROR_016, NRS_STOP_PROCESS_EVENT_NOTIFY);
      MessageBoxA(0, ErrorString, "error", MB_ICONERROR);
      ServerFunction_09(0);
      break;
    case NRS_CONTINUE_PROCESS_EVENT_NOTIFY:
      //通知系统继续处理事件通知
      //和窗口组建相关,不处理
      sprintf(ErrorString, "%s\n\nIntra error number is %d.", ERROR_016, NRS_CONTINUE_PROCESS_EVENT_NOTIFY);
      MessageBoxA(0, ErrorString, "error", MB_ICONERROR);
      ServerFunction_09(0);
      break;
    */
    case NRS_DO_EVENTS:
      //通知Windows系统处理所有已有事件
      //我不觉得这种处理方式很好,确定的说,是一种很差的处理方式
      Sleep(1);
      break;
    case NRS_GET_UNIT_DATA_TYPE:
      //成功返回有效的 DATA_TYPE
      //和窗口组建相关,不处理
      sprintf(ErrorString, "%s\n\nIntra error number is %d.", ERROR_016, NRS_GET_UNIT_DATA_TYPE);
      MessageBoxA(0, ErrorString, "error", MB_ICONERROR);
      ServerFunction_09(0);
      break;  
    case NRS_FREE_ARY:
      //释放指定数组数据
      //不会处理T_T,:(
      MessageBoxA(0, ERROR_020, "error", MB_ICONERROR);
      ServerFunction_09(0);
      break;
    case NRS_MALLOC:
      //分配指定空间的内存,所有与易程序交互的内存都必须使用本通知分配
      temppoint = HeapAlloc(ThisHeap, 0, dwParam1);
      if(temppoint == NULL)
      {
        if(dwParam2 == 0)
        {
          MessageBoxA(0, ERROR_017, "error", MB_ICONERROR);
          ServerFunction_09(0);
          return 0;
        }
        else
        {
          return 0;
        }
      }
      return (INT)temppoint;
    case NRS_MFREE:
      //释放已分配的指定内存
      if(dwParam1 != NULL)
      {
        HeapFree(ThisHeap, 0, (void *)dwParam1);
      }
      break;
    case NRS_MREALLOC:
      //重新分配内存
      temppoint = HeapReAlloc(ThisHeap, 0, (void *)dwParam1, dwParam2);
      if(temppoint == NULL)
      {
        MessageBoxA(0, ERROR_018, "error", MB_ICONERROR);
        ServerFunction_09(0);
        return 0;
      }
      return (INT)temppoint;
    case NRS_RUNTIME_ERR:
      //通知系统已经产生运行时错误
      sprintf(ErrorString, "%s\n\nError String is %s", ERROR_019, (char*)dwParam1);
      MessageBoxA(0, ErrorString, "error", MB_ICONERROR);
      ServerFunction_09(0);
      break;
    case NRS_EXIT_PROGRAM:
      //通知系统退出用户程序
      ServerFunction_09(dwParam1);
      break;
    case NRS_EVENT_NOTIFY2:
      //以第二类方式通知系统产生了事件
      //和窗口组建相关,不处理
      sprintf(ErrorString, "%s\n\nIntra error number is %d.", ERROR_016, NRS_EVENT_NOTIFY2);
      MessageBoxA(0, ErrorString, "error", MB_ICONERROR);
      ServerFunction_09(0);
      break;
    case NRS_GET_WINFORM_COUNT:
      //返回当前程序的窗体数目
      //和窗口组建相关,不处理
      sprintf(ErrorString, "%s\n\nIntra error number is %d.", ERROR_016, NRS_GET_WINFORM_COUNT);
      MessageBoxA(0, ErrorString, "error", MB_ICONERROR);
      ServerFunction_09(0);
      break;
    case NRS_GET_WINFORM_HWND:
      //返回指定窗体的窗口句柄,如果该窗体尚未被载入,返回NULL
      //和窗口组建相关,不处理
      sprintf(ErrorString, "%s\n\nIntra error number is %d.", ERROR_016, NRS_GET_WINFORM_HWND);
      MessageBoxA(0, ErrorString, "error", MB_ICONERROR);
      ServerFunction_09(0);
      break;
    case NRS_GET_BITMAP_DATA:
      //返回指定HBITMAP的图片数据,成功返回包含BMP图片数据的HGLOBAL句柄,失败返回NULL
      //和窗口组建相关,不处理
      sprintf(ErrorString, "%s\n\nIntra error number is %d.", ERROR_016, NRS_GET_BITMAP_DATA);
      MessageBoxA(0, ErrorString, "error", MB_ICONERROR);
      ServerFunction_09(0);
      break;
    case NRS_FREE_COMOBJECT:
      //通知系统释放指定的DTP_COM_OBJECT类型COM对象
      //不支持COM对象,不处理
      sprintf(ErrorString, "%s\n\nIntra error number is %d.", ERROR_016, NRS_FREE_COMOBJECT);
      MessageBoxA(0, ErrorString, "error", MB_ICONERROR);
      ServerFunction_09(0);
      break;  
    case NRS_CHK_TAB_VISIBLE:
      //当选择夹子夹被切换后, 使用本消息通知易系统
      //和窗口组建相关,不处理
      sprintf(ErrorString, "%s\n\nIntra error number is %d.", ERROR_016, NRS_CHK_TAB_VISIBLE);
      MessageBoxA(0, ErrorString, "error", MB_ICONERROR);
      ServerFunction_09(0);
      break;      
    case NRS_GET_PRG_TYPE:
      //返回当前用户程序的类型,为PT_DEBUG_RUN_VER(调试版)或PT_RELEASE_RUN_VER(发布版)
      return PT_RELEASE_RUN_VER;
    default:
      //如果发生例外,不处理
      break;
  }
  
  return 0;
}

bool Init(void)
{
  ThisHeap = HeapCreate(0, 0x1000, 0);
  if(ThisHeap == NULL)
  {
    return false;
  }

  MyNotifySys = ThisNotifySys;

  return true;
}

void _cdecl ServerFunction_00(UINT32 Param1)
{
  
  sprintf(ErrorString, "%s\n\nIntra error number is %d.", ERROR_006, Param1);
  MessageBoxA(0, ErrorString, "error", MB_ICONERROR);
  
  ServerFunction_09(0);
  
  return;
}

__declspec(naked) void _stdcall ServerFunction_01(void)
{

  __asm
  {
    pop temp
    push eax
    pop DllCmdNO
  }

  ThisDllCmd = DllCmdHead;
  ThisDllCmd += DllCmdNO;

  if((* ThisDllCmd->DllFileName) == NULL)
  {
    i = 0;
    while((* DefaultSystemAPI[i]) != NULL)
    {
      ThisLibrary = LoadLibrary(DefaultSystemAPI[i]);
      UnKnowFun = (UNKNOWFUN)GetProcAddress(ThisLibrary, ThisDllCmd->DllCmdName);
      if(UnKnowFun != NULL)
      {
        __asm
        {
          //call UnKnowFun
          //这个地方可能会引起杀毒软件的误报,如果有必要的话,需要处理一下
          push temp
          jmp UnKnowFun
        }
        break;
      }
      else
      {
        FreeLibrary(ThisLibrary);
        i++;
      }

    }

    if(UnKnowFun == NULL)
    {
      ServerFunction_00(0);
    }
    
  }
  else
  {
    ThisLibrary = LoadLibrary(ThisDllCmd->DllFileName);
    UnKnowFun = (UNKNOWFUN)GetProcAddress(ThisLibrary, ThisDllCmd->DllCmdName);
    if(UnKnowFun != NULL)
    {
      __asm
      {
        //call UnKnowFun
        push temp
        jmp UnKnowFun
      }
    }
    else
    {
      ServerFunction_00(0);
    }    
  }
  
  __asm
  {
    push eax
  }
  
  FreeLibrary(ThisLibrary);
  
  __asm
  {
    pop eax
    push temp
    ret
  }
  
}

__declspec(naked) void _cdecl ServerFunction_02(void)
{
  
  __asm
  {
    push ebp
    mov ebp,esp
    mov LibCmdNO,eax
  }
  ThisLibInfo = LibInfoHead;
  ThisLibInfo += LibCmdNO;
  if(ThisLibInfo->ThisLibHandle == NULL || ThisLibInfo->ThisLibInfo == NULL)
  {
    sprintf(ErrorString, "%s\n\nIntra error string is \"%s\".", ERROR_014, ThisLibInfo->ThisLibName);
    MessageBoxA(0, ErrorString, "error", MB_ICONERROR);  
    ServerFunction_09(0);  
  }
  ThisCmdsFuncHead = &(ThisLibInfo->ThisLibInfo->m_pCmdsFunc);
  __asm
  {
    mov edx,[ThisCmdsFuncHead]
    add ebx,[edx]
    lea edx,dword ptr ss:[esp+0x0c]
    sub esp,0x0c
    push edx
    push dword ptr ss:[esp+0x18]
    mov dword ptr ss:[esp+0x08],0
    mov dword ptr ss:[esp+0x0c],0
    mov dword ptr ss:[esp+0x10],0
    lea edx,dword ptr ss:[esp+0x08]
    push edx
    call dword ptr ds:[ebx]
    mov eax,dword ptr ss:[esp+0x0c]
    mov edx,dword ptr ss:[esp+0x10]
    mov ecx,dword ptr ss:[esp+0x14]
    mov esp,ebp
    pop ebp
    retn
  }
}

__declspec(naked) void _cdecl ServerFunction_03(void)
{
  
  __asm
  {
    push ebp
    mov ebp,esp
    mov LibCmdNO,0
    mov ThisBaseCmdOffset,ebx
  }
  temp = 0;
  FindOK = false;
  while(KernelBaseCmd[temp].CmdOffset != -1)
  {
    if(KernelBaseCmd[temp].CmdOffset == ThisBaseCmdOffset)
    {
      FindOK = true;
      ThisExecuteCmdPoint = &(KernelBaseCmd[temp].CmdPoint);
      break;
    }
    temp++;
  }
  if(FindOK == false)
  {
    ThisLibInfo = LibInfoHead;
    ThisLibInfo += LibCmdNO;
    if(ThisLibInfo->ThisLibHandle == NULL || ThisLibInfo->ThisLibInfo == NULL)
    {
      sprintf(ErrorString, "%s\n\nIntra error string is \"%s\".", ERROR_015, ThisLibInfo->ThisLibName);
      MessageBoxA(0, ErrorString, "error", MB_ICONERROR);    
      ServerFunction_09(0);  
    }
    ThisCmdsFuncHead = &(ThisLibInfo->ThisLibInfo->m_pCmdsFunc);

    __asm
    {
      mov eax,[ThisCmdsFuncHead]
      add ebx,dword ptr ds:[eax]
    }
  }
  else
  {
    __asm
    {
      mov ebx,ThisExecuteCmdPoint
    }
  }
  __asm
  {
    lea eax,dword ptr ss:[esp+0x0c]
    sub esp,0x0c
    push eax
    push dword ptr ss:[esp+0x18]
    xor eax,eax
    mov dword ptr ss:[esp+0x08],eax
    mov dword ptr ss:[esp+0x0c],eax
    mov dword ptr ss:[esp+0x10],eax
    lea edx,dword ptr ss:[esp+0x08]
    push edx
    call dword ptr ds:[ebx]
    mov eax,dword ptr ss:[esp+0x0C]
    mov edx,dword ptr ss:[esp+0x10]
    mov ecx,dword ptr ss:[esp+0x14]
    mov esp,ebp
    pop ebp
    retn  
  }

}

void _cdecl ServerFunction_04(void)
{
  MessageBoxA(0, ERROR_012, "error", MB_ICONERROR);
  ServerFunction_09(0);
  return;
}

void _cdecl ServerFunction_05(void)
{
  MessageBoxA(0, ERROR_013, "error", MB_ICONERROR);
  ServerFunction_09(0);
  return;
}

__declspec(naked) UINT32 _cdecl ServerFunction_06(UINT32 Param1)
{
  __asm
  {
    push ebp
    mov ebp,esp
    push ecx
    mov eax,Param1
    mov ecx,ThisHeap
  }
  HeapAlloc(ThisHeap, 0, Param1);
  __asm
  {
    mov dword ptr ss:[ebp-0x04],eax
    cmp dword ptr ss:[ebp-0x04],0
    jnz okey
  }
  MessageBoxA(0, ERROR_008, "error", MB_ICONERROR);
  ServerFunction_09(0);
  __asm
  {
okey:
    mov eax,dword ptr ss:[ebp-0x04]
    mov esp,ebp
    pop ebp
    retn
  }
}

__declspec(naked) UINT32 _cdecl ServerFunction_07(UINT32 Param1, UINT32 Param2)
{
  __asm
  {
    push ebp
    mov ebp,esp
    sub esp,0x0c
    cmp Param1,0
    jnz a
    mov eax,Param2
    push eax
    call ServerFunction_06
    add esp,0x04
    jmp end    
a:    
  }
  HeapReAlloc(ThisHeap, 0, (void *)Param1, Param2);
  __asm
  {
    mov Param1,eax
    cmp Param1,0
    jnz b
  }
  MessageBoxA(0, ERROR_010, "error", MB_ICONERROR);
  ServerFunction_09(0);
  __asm
  {
    
b:
    mov eax,Param1
end:
    mov esp,ebp
    pop ebp
    retn
  }
}

void _cdecl ServerFunction_08(UINT32 Param1)
{
  if(Param1 != 0)
  {
    HeapFree(ThisHeap, 0, (void *)Param1);  
  }

  return;
}

void _cdecl ServerFunction_10(UINT32 Param1)
{  
  return;
}

void _cdecl ServerFunction_11(UINT32 Param1)
{
  MessageBoxA(0, ERROR_011, "error", MB_ICONERROR);
  ServerFunction_09(0);
  return;
}

void _cdecl ServerFunction_12(UINT32 Param1)
{
  SaveAAddress = Param1;
  return;
}

void InitServerPointTable(void)
{
  ServerPointTable[0] = (UINT32)ServerFunction_00;
  ServerPointTable[1] = (UINT32)ServerFunction_01;
  ServerPointTable[2] = (UINT32)ServerFunction_02;
  ServerPointTable[3] = (UINT32)ServerFunction_03;
  ServerPointTable[4] = (UINT32)ServerFunction_04;
  ServerPointTable[5] = (UINT32)ServerFunction_05;
  ServerPointTable[6] = (UINT32)ServerFunction_06;
  ServerPointTable[7] = (UINT32)ServerFunction_07;
  ServerPointTable[8] = (UINT32)ServerFunction_08;
  ServerPointTable[9] = (UINT32)ServerFunction_09;
  ServerPointTable[10] = (UINT32)ServerFunction_10;
  ServerPointTable[11] = (UINT32)ServerFunction_11;
  ServerPointTable[12] = (UINT32)ServerFunction_12;
}

void UpdataServerPointTable(void)
{
  ptemp = (UINT32 *)((UINT32)ECodeHeaderInfo + pHelpFuncSectionOffset->m_nRecordOffset);
  for(i = 0; i <= ESERVERCOUNT - 1; i++)
  {
    (* ptemp) = ServerPointTable[i];
    ptemp++;
  }
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
  
  //初始化内部堆栈
  if(Init() == false)
  {
    MessageBoxA(0, ERROR_009, "error", MB_ICONERROR);
    return 0;
  }

  //得到当前命令行
  ThisCmdLine = lpCmdLine;
  
  //获取当前运行环境
  GetModuleFileName(NULL, FileName_Full, 256);
  strcpy(FileName_Name, PathFindFileName(FileName_Full));
  temp = strlen(FileName_Full) - strlen(FileName_Name);
  memcpy(FileName_Path, FileName_Full, temp);
  FileName_Path[temp] = 0;

  
  //获取当前进程基址,遍历SectionTable查找易格式原体
  DosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL);
  
  if(DosHeader == NULL)
  {
    MessageBoxA(0, ERROR_001, "error", MB_ICONERROR);
    return 0;
  }

  NtHeader = (PIMAGE_NT_HEADERS)((UINT32)DosHeader + DosHeader->e_lfanew);
  NumberOfSections = NtHeader->FileHeader.NumberOfSections;
  
  SectionHeader = (PIMAGE_SECTION_HEADER)((UINT32)NtHeader + sizeof(IMAGE_NT_HEADERS));

  FindOK = false;
  for(i = 1; i <= NumberOfSections; i++)
  {
    
    memcpy(SectionName, SectionHeader->Name, IMAGE_SIZEOF_SHORT_NAME);
    SectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = 0;

    //寻找易格式所在节的方法是:简单的比较当前SectionName是否是“.ecode”
    if(strcmp(SectionName, ESECTIONNAME) == 0)
    {
      //找到了易格式所在的节
      FindOK = true;
      break;
    }

    SectionHeader++;

  }
  
  if(FindOK == false)
  {
    MessageBoxA(0, ERROR_002, "error", MB_ICONERROR);
    return 0;
  }
  
  //定位易格式原体,取易格式原体所在节的基址
  ESectionVA = (UINT32)DosHeader + (UINT32)SectionHeader->VirtualAddress;
  ECodeHeaderInfo = (PAPP_HEADER_INFO)ESectionVA;

  if(ECodeHeaderInfo == NULL)
  {
    MessageBoxA(0, ERROR_003, "error", MB_ICONERROR);
    return 0;
  }

  if(ECodeHeaderInfo->m_dwMark != NEW_E_APP_MARK)
  {
    MessageBoxA(0, ERROR_004, "error", MB_ICONERROR);
    return 0;
  }

  //获取易格式初始化必需的的数据

  //获取各个重要数据段的RVA
  pConstSectionOffset = (PSECTION_INFO)((UINT32)ECodeHeaderInfo + ECodeHeaderInfo->m_nConstSectionOffset);
  pWinFormSectionOffset = (PSECTION_INFO)((UINT32)ECodeHeaderInfo + ECodeHeaderInfo->m_nWinFormSectionOffset);
  pHelpFuncSectionOffset = (PSECTION_INFO)((UINT32)ECodeHeaderInfo + ECodeHeaderInfo->m_nHelpFuncSectionOffset);
  pCodeSectionOffset = (PSECTION_INFO)((UINT32)ECodeHeaderInfo + ECodeHeaderInfo->m_nCodeSectionOffset);
  pVarSectionOffset = (PSECTION_INFO)((UINT32)ECodeHeaderInfo + ECodeHeaderInfo->m_nVarSectionOffset);
  
  //获取DLL命令信息数组
  if(ECodeHeaderInfo->m_nDllCmdCount > 0)
  {
    DllCmdHead = (PDLLCMD)malloc(sizeof(DLLCMD) * ECodeHeaderInfo->m_nDllCmdCount);
    if(DllCmdHead == NULL)
    {
      MessageBoxA(0, ERROR_007, "error", MB_ICONERROR);
      return 0;
    }

    ThisDllCmd = DllCmdHead;

    for(i = 1; i <= (UINT32)ECodeHeaderInfo->m_nDllCmdCount; i++)
    {
      ThisDllCmd->DllFileName = (char *)((UINT32)ECodeHeaderInfo + pConstSectionOffset->m_nRecordOffset + (*(UINT *)((UINT32)ECodeHeaderInfo + sizeof(APP_HEADER_INFO) + (i - 1) * sizeof(INT))));
      ThisDllCmd->DllCmdName = (char *)((UINT32)ECodeHeaderInfo + pConstSectionOffset->m_nRecordOffset + (*(UINT *)((UINT32)ECodeHeaderInfo + sizeof(APP_HEADER_INFO) + (i + ECodeHeaderInfo->m_nDllCmdCount - 1) * sizeof(INT))));
      
      ThisDllCmd++;
    }

  }
  
  //获取需要的支持库并加载
  LibStringHead = (char *)((UINT32)ECodeHeaderInfo + sizeof(APP_HEADER_INFO) + ECodeHeaderInfo->m_nDllCmdCount * sizeof(INT) * 2);

  //统计需要加载的支持库数量
  ThisLibString = LibStringHead;
  LibCount = 0;
  while((* ThisLibString) != NULL)
  {
    LibCount++;
    ThisLibString += (strlen(ThisLibString) + 1);
  }

  //加载支持库
  LibInfoHead = (PLIBINFO)malloc(sizeof(LIBINFO) * LibCount);

  ThisLibInfo = LibInfoHead;

  ThisLibString = LibStringHead;

  while((* ThisLibString) != NULL)
  {
    temp = 0;
    while((* (ThisLibString + temp)) != 0x0d)
    {
      ThisLibStringInfo.LibName[temp] = (* (ThisLibString + temp));
      temp++;
    }
    ThisLibStringInfo.LibName[temp] = 0;

    temp += 1;
    while((* (ThisLibString + temp)) != 0x0d)
    {
      ThisLibStringInfo.ThisGUID[temp - strlen(ThisLibStringInfo.LibName) - 1] = (* (ThisLibString + temp));
      temp++;
    }
    ThisLibStringInfo.ThisGUID[temp] = 0;
    
    ThisLibInfo->ThisLibHandle = NULL;
    ThisLibInfo->ThisLibInfo = NULL;
    strcpy(ThisLibInfo->ThisLibName, ThisLibStringInfo.LibName);
    
    strcpy(ThisLibFileName, ThisLibStringInfo.LibName);
    strcat(ThisLibFileName, ".fne");

    FindOK = false;

    ThisLibInfo->ThisLibHandle = LoadLibrary(ThisLibFileName);
    if(ThisLibInfo->ThisLibHandle == NULL)
    {
      strcpy(ThisLibFileName, ThisLibStringInfo.LibName);
      strcat(ThisLibFileName, ".fnr");

      FindOK = false;
      
      ThisLibInfo->ThisLibHandle = LoadLibrary(ThisLibFileName);

      if(ThisLibInfo->ThisLibHandle == NULL)
      {
        //没有加载成功,继续加载下一个支持库
      }
      else
      {
        FindOK = true;
      }

    }
    else
    {
      FindOK = true;
    }
    
    //加载成功,开始获取支持库信息
    if(FindOK == true)
    {
      GetThisNewInfo = (PFN_GET_LIB_INFO)GetProcAddress(ThisLibInfo->ThisLibHandle, FUNCNAME_GET_LIB_INFO);  
      
      //初始化核心支持库
      GetNewSock = (GETNEWSOCK)GetProcAddress(ThisLibInfo->ThisLibHandle, FUNCNAME_GET_NEW_SOCK);
      
      if(GetNewSock != NULL)
      {
        //这是一段罪恶的代码,江山从此易主。希望新版本的核心支持库能分离初始化函数和加载函数
        GetNewSock(1000);
        __asm
        {
          pop edx
          mov edx,ESectionVA
          push edx  
          call eax      
        }
        Exit();
        return 0;
      }
      
      if(GetThisNewInfo == NULL)
      {
        //载入的库没有输出FUNCNAME_GET_LIB_INFO函数,需要卸载掉
        FreeLibrary(ThisLibInfo->ThisLibHandle);
        ThisLibInfo->ThisLibHandle = NULL;
      }
      else
      {
        ThisLibInfo->ThisLibInfo = GetThisNewInfo();

        if(ThisLibInfo->ThisLibInfo == NULL)
        {
          //输出的PLIB_INFO结构为空,需要卸载这样的支持库
          FreeLibrary(ThisLibInfo->ThisLibHandle);
          ThisLibInfo->ThisLibHandle = NULL;
          ThisLibInfo->ThisLibInfo = NULL;
        }
        else
        {
          if(strcmp(ThisLibInfo->ThisLibInfo->m_szGuid, ThisLibStringInfo.ThisGUID) != 0)
          {
            //加载的支持库和需要的支持库GUID不同,需要卸载支持库
            FreeLibrary(ThisLibInfo->ThisLibHandle);
            ThisLibInfo->ThisLibHandle = NULL;
            ThisLibInfo->ThisLibInfo = NULL;
          }
          else
          {
            //为当前支持库提供Notify函数指针
            ThisNotifyLib = ThisLibInfo->ThisLibInfo->m_pfnNotify;
            if(ThisNotifyLib != NULL)
            {
              ThisNotifyLib(NL_SYS_NOTIFY_FUNCTION, (DWORD)MyNotifySys, 0);
            }

          }

        }      
      }
    }


    ThisLibInfo++;
    
    ThisLibString += (strlen(ThisLibString) + 1);
  }

  
  //获取易格式代码的起始指令地址
  ECodeStart = (ECODESTART)((UINT32)ECodeHeaderInfo + (UINT32)ECodeHeaderInfo->m_nStartCodeOffset);
  
  if(ECodeStart == NULL)
  {
    MessageBoxA(0, ERROR_005, "error", MB_ICONERROR);
    return 0;    
  }
  
  //遍历易格式中所有的数据段,对每个数据段中的重定位信息进行校正
  temp = (UINT32)ECodeHeaderInfo->m_nBeginSectionOffset;
  
  while(temp != 0xFFFFFFFF)
  {
    ThisSectionInfo = (PSECTION_INFO)((UINT32)ECodeHeaderInfo + temp);
    
    if(ThisSectionInfo->m_nReLocationItemCount > 0)
    {
      ThisRelocationInfo = (PRELOCATION_INF)((UINT32)ThisSectionInfo + sizeof(SECTION_INFO));
      for(i = 1; i <= (UINT32)ThisSectionInfo->m_nReLocationItemCount; i++)
      {
        
        ptemp = (UINT32 *)((UINT32)ECodeHeaderInfo + ThisSectionInfo->m_nRecordOffset + ThisRelocationInfo->m_dwOffset);
        
        switch(ThisRelocationInfo->m_btType)
        {
          case RT_HELP_FUNC:  
            (* ptemp) = (* ptemp) + (UINT32)ECodeHeaderInfo + pHelpFuncSectionOffset->m_nRecordOffset;
            break;
          case RT_CONST:
            (* ptemp) = (* ptemp) + (UINT32)ECodeHeaderInfo + pConstSectionOffset->m_nRecordOffset;
            break;
          case RT_GLOBAL_VAR:
            (* ptemp) = (* ptemp) + (UINT32)ECodeHeaderInfo + pVarSectionOffset->m_nRecordOffset;
            break;
          case RT_CODE:
            (* ptemp) = (* ptemp) + (UINT32)ECodeHeaderInfo + pCodeSectionOffset->m_nRecordOffset;
            break;
          default:    
            break;
        }

        ThisRelocationInfo++;  
      }
    }
    temp = (UINT32)ThisSectionInfo->m_nNextSectionOffset;
  }

  //初始化服务指针表
  InitServerPointTable();
  UpdataServerPointTable();

  //至此初始化操作全部完成,转交控制权给易程序
  ECodeStart();

  //清除内部堆栈,准备结束
  Exit();

  return 0;
}


/////////////////////////////////////////////////////////////////////////


上面的代码也是ZanMoon计划(斩月计划)的核心组件MicroLoader的源代码,关于ZanMoon计划,详情请登陆http://monkeycz.blogbus.com。

关于版权问题:由于涉及到部分头文件的版权问题,我没有发布完整的工程,请大家见谅。这个项目的全部工程,除引用和包含的第三方文档、代码外,全部源代码符合GPL规范。






monkeycz
2005/11/13