hi,各位新年快乐~拜个晚年
大概前年底的时候,开始想往自制的os tinix里移植一个编译器,构建一个传说中的os生态,哈哈
于是看雪上面找来luocong大神的lcc源码进行研究,改着改着发现要移植是不可能的事情。
但是研究的过程中发现了lcc源码的不少问题,也有了一些功能改进想法和研究兴趣,顺便也想了解下编译原理这门学科。慢慢的做了好多现在看来很2的修改。
也许可以改进成一个不错的脚本解释器,发出来大家一起研究学习下
luocong大神的lcc在这个帖子上
http://bbs.pediy.com/showthread.php?t=149966
分发遵循BSD协议,有改进也可以共享下
做了很多修改,大多是为了实现A功能首先得实现B功能,实现期间发现,干脆再实现个C功能......
由于是很早以前改的,忘了很多,印象里做了以下几点修改:
1,修复部分语法解析上的bug,不赘述,可通过查看两份代码区别来确认。
2,新增一部分语法支持,如取地址符,指针符,全局变量等。这部分主要实现在,虚拟机指令的修改,代码生成时全局内存分配的修改。
3,为虚拟机添加调试功能
启动时-d参数将进入调试模式,调试器将停在第一条虚拟指令li_i指令上
断点功能(支持符号)及调用栈查看、内存查看等功能
4,可变参数调用约定的支持
5,define宏的简单支持
如
#define MUL(_a,_b,_c) ((_a)*(_b)*(_c))
6,在脚本解释器和vc run-time library之间做了一层转发stub,因为这个虚拟机也是通过栈传参,所以这个转发实现的比较简单。这层转发也依靠上述的define宏支持和可变参数的支持。
如
定义宏
#define CRT_LIB_NAME "msvcr90.dll"
#define malloc(_size) cdecl_wrapper(CRT_LIB_NAME, "malloc", _size)
代码中的malloc(100)将被展开为
cdecl_wrapper("msvcr90.dll", "malloc", 100)
cdecl_wrapper的实现如下
INT cdecl_wrapper( CONST CHAR *libname, CONST CHAR *funname, PINT sp, INT ParamSize )
{
HMODULE hLib = NULL;
PVOID pFn = NULL;
INT retvalue = 0;
INT nParamCount = ParamSize / sizeof_i - 2;
INT nParamSize = ParamSize - sizeof_i*2;
PINT pParam = &sp[2+nParamCount];
hLib = GetModuleHandle(libname);
if (hLib == NULL)
hLib = LoadLibrary(libname);
if (hLib == NULL)
{
VM_Error(emVEI_Runtime_Error_Can_not_find_library_x, libname);
return 0;
}
pFn = (PVOID)GetProcAddress(hLib, funname);
if (pFn == NULL)
{
VM_Error(emVEI_Runtime_Error_Can_not_find_method_x_in_x, funname, libname);
return 0;
}
__try
{
__asm
{
pusha
mov eax, pParam
mov ecx, nParamCount
l1:
cmp ecx, 0
je l2
mov ebx, [eax]
push ebx
sub eax, 4
dec ecx
jmp l1
l2:
call pFn
mov retvalue, eax
add esp, nParamSize
popa
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
VM_Error(emVEI_Runtime_Error_An_exception_occurs_during_libcall_x, funname);
}
//FreeLibrary(hLib);
return retvalue;
}
使用这个简单的转发,可以直接调用msvcrt中的大部分函数。
如crt.h脚本头文件中定义的
//mem
#define malloc(_size) cdecl_wrapper(CRT_LIB_NAME, "malloc", _size)
#define free(_buff) cdecl_wrapper(CRT_LIB_NAME, "free", _buff)
#define memset(_buff, _set, _size) cdecl_wrapper(CRT_LIB_NAME, "memset", _buff, _set, _size)
#define memmove(_dest, _src, _count) cdecl_wrapper(CRT_LIB_NAME, "memmove", _dest, _src, _count)
#define memcpy(_dest, _src, _count) cdecl_wrapper(CRT_LIB_NAME, "memcpy", _dest, _src, _count)
#define memchr(_buff, _ch, _count) cdecl_wrapper(CRT_LIB_NAME, "memmove", _buff, _ch, _count)
#define memcmp(_dest, _src, _count) cdecl_wrapper(CRT_LIB_NAME, "memcmp", _dest, _src, _count)
//file
/* Seek method constants */
#define SEEK_CUR 1
#define SEEK_END 2
#define SEEK_SET 0
#define fopen(_path, _mode) cdecl_wrapper(CRT_LIB_NAME, "fopen", _path, _mode)
#define fclose(_stream) cdecl_wrapper(CRT_LIB_NAME, "fclose", _stream)
#define feof(_stream) cdecl_wrapper(CRT_LIB_NAME, "feof", _stream)
#define ftell(_stream) cdecl_wrapper(CRT_LIB_NAME, "ftell", _stream)
#define fseek(_stream, _offset, _fromwhere) cdecl_wrapper(CRT_LIB_NAME, "fseek", _stream, _offset, _fromwhere)
#define fread(_buffer, _size, _count, _stream) cdecl_wrapper(CRT_LIB_NAME, "fread", _buffer, _size, _count, _stream)
#define fwrite(_buffer, _size, _count, _stream) cdecl_wrapper(CRT_LIB_NAME, "fwrite", _buffer, _size, _count, _stream)
//string
#define strcpy(_dest, _src) cdecl_wrapper(CRT_LIB_NAME, "strcpy", _dest, _src)
#define strncpy(_dest, _src, _count) cdecl_wrapper(CRT_LIB_NAME, "strncpy", _dest, _src, _count)
#define strcat(_dest, _src) cdecl_wrapper(CRT_LIB_NAME, "strcat", _dest, _src)
#define strncat(_dest, _src, _count) cdecl_wrapper(CRT_LIB_NAME, "strncat", _dest, _src)
#define strcmp(_cs, _ct) cdecl_wrapper(CRT_LIB_NAME, "strcmp", _cs, _ct)
#define strncmp(_cs, _ct, _count) cdecl_wrapper(CRT_LIB_NAME, "strncmp", _cs, _ct, _count)
#define strchr(_s, _c) cdecl_wrapper(CRT_LIB_NAME, "strchr", _s, _c)
#define strrchr(_s, _c) cdecl_wrapper(CRT_LIB_NAME, "strrchr", _s, _c)
#define strspn(_cs, _ct) cdecl_wrapper(CRT_LIB_NAME, "strspn", _cs, _ct)
#define strcspn(_cs, _ct) cdecl_wrapper(CRT_LIB_NAME, "strcspn", _cs, _ct)
#define strpbrk(_cs, _ct) cdecl_wrapper(CRT_LIB_NAME, "strpbrk", _cs, _ct)
#define strstr(_cs, _ct) cdecl_wrapper(CRT_LIB_NAME, "strstr", _cs, _ct)
#define strlen(_s) cdecl_wrapper(CRT_LIB_NAME, "strlen", _s)
#define strtok(_s, _ct) cdecl_wrapper(CRT_LIB_NAME, "strtok", _s, _ct)
#define strtol(_nptr, _endptr, _base) cdecl_wrapper(CRT_LIB_NAME, "strtol", _nptr, _endptr, _base)
如通过这层转发调用crt的fopen、fprintf函数进行简单的文件操作
脚本源码
#include "crt.h"
int main()
{
int f = fopen("out.txt","w");
fprintf(f, "测试数据");
fclose(f);
return 0;
}
这层转发大大的增加了脚本实现各种功能的可能性,可以自由发挥想象,比如座一层stdcall约定的转发,调用个MessageBox也不是太难的事情。
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法