| 赞 | 2 |
| VIP | |
| 好人卡 | |
| 积分 | 1 |
| 经验 | |
| 最后登录 | 2024-3-18 |
| 在线时间 | 54 小时 |
- 梦石
- 0
- 星屑
- 81
- 在线时间
- 54 小时
- 注册时间
- 2008-12-24
- 回帖
- 188
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有账号?注册会员
×
我已经很久不玩 RMXP了。
某个瞬间我看到了一个 iD[猫哥哥] 发的一篇文章 [RMXP发布] RMXP脚本编辑器不完全调教= =||[更新到v1.1]
虽然去 玩C++ 很久了,但也没有写出一个成品。。。唉。
废话不多说了。
首先编译 scintilla 开源库 在 DLLmain 入口函数 加入 LoadLibrary() -》 代替注入。
[pre lang="c++" line="0"]
// 这个是拦截 脚本编辑器 创建 裸函数。。。 this call
__declspec(naked) int sub_49B840()
{
_asm
{
push ebp;
mov ebp, esp;
push dword ptr [ebp+16];
push dword ptr [ebp+12];
push dword ptr [ebp+8];
push ecx;
call SCICreateEx;
mov esp, ebp;
pop ebp;
ret 12;
}
}
CSimHook g_pHookSCICreate(0x09B840, (int)(sub_49B840));
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
{
g_pHookSCICreate.Rehook();
break;
}
case DLL_PROCESS_DETACH:
{
break;
}
}
return TRUE;
}
HWND g_hSCIWnd = NULL;
HWND g_hSCIWndParent = NULL;
SciFnDirect g_fnDirect = NULL;
sptr_t g_ptrDirect = NULL;
WNDPROC g_pfnWndProc = NULL;
WNDPROC g_pfnParentWndProc = NULL;
__inline sptr_t SendEditor(unsigned int iMessage, uptr_t wParam = 0, sptr_t lParam = 0)
{
return g_fnDirect(g_ptrDirect, iMessage, wParam, lParam);
}
#define MARGIN_FOLD_INDEX 2
#include "xpm.h"
int WINAPI SCICreateEx(int pThis, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// 初始化 其实这个放在 子类化后的销毁消息中最好
g_hSCIWnd = NULL;
g_hSCIWndParent = NULL;
g_fnDirect = NULL;
g_ptrDirect = NULL;
g_pfnWndProc = NULL;
g_pfnParentWndProc = NULL;
// 调用源流程
g_pHookSCICreate.Unhook();
int callptr = g_pHookSCICreate.GetPtr();
_asm
{
pushad; // 其实非 this call fast call 不一定要保护寄存器
push dword ptr [lParam];
push dword ptr [wParam];
push dword ptr [uMsg];
mov ecx, dword ptr [pThis];
call dword ptr [callptr];
mov dword ptr [callptr], eax;
popad;
}
g_pHookSCICreate.Rehook();
// 进行修正
int * pSCIWnd = (int*)(pThis + 0x20);
g_hSCIWnd = (HWND)(*pSCIWnd);
if (g_hSCIWnd != NULL)
{
// 取父窗口
g_hSCIWndParent = ::GetParent(g_hSCIWnd);
if (g_hSCIWndParent != NULL)
{
g_fnDirect = (SciFnDirect)SendMessage(g_hSCIWnd, SCI_GETDIRECTFUNCTION, 0, 0);
g_ptrDirect = (sptr_t)SendMessage(g_hSCIWnd, SCI_GETDIRECTPOINTER, 0, 0);
if ((g_ptrDirect != NULL) && (g_fnDirect != NULL))
{
// 子类化窗口
g_pfnWndProc = (WNDPROC)::SetWindowLong(g_hSCIWnd, GWL_WNDPROC, (long)SCIWndProc);
g_pfnParentWndProc = (WNDPROC)::SetWindowLong(g_hSCIWndParent, GWL_WNDPROC, (long)SCIParentWndProc);
SendEditor(SCI_SETCODEPAGE, SC_CP_UTF8); // utf - 8
SendEditor(SCI_SETLEXER, SCLEX_RUBY); // 设置 RUBY 解析器
SendEditor(SCI_STYLESETFONT, STYLE_DEFAULT, (sptr_t)"Courier New"); // 设置默认字体
SendEditor(SCI_STYLESETSIZE, STYLE_DEFAULT, 10); // 设置默认字号
SendEditor(SCI_SETPROPERTY, (sptr_t)"styling.within.preprocessor", (sptr_t)"1"); // 使预处理符后面的关键词能够使用高亮着色风格
// 设置关键字
// 设置风格
SendEditor(SCI_STYLESETFORE, SCE_RB_DEFAULT, RGB(255, 255, 255));
SendEditor(SCI_STYLESETFORE, SCE_RB_ERROR, RGB(255, 0, 0));
SendEditor(SCI_STYLESETFORE, SCE_RB_COMMENTLINE, RGB(0, 128, 0)); // 行注释
// SendEditor(SCI_STYLESETFORE, SCE_RB_POD 3
SendEditor(SCI_STYLESETFORE, SCE_RB_NUMBER, RGB(128, 0, 0)); // 数字
//SendEditor(SCI_STYLESETFORE, SCE_RB_WORD 5
SendEditor(SCI_STYLESETFORE, SCE_RB_STRING, RGB(128, 0, 128)); // 字符串
SendEditor(SCI_STYLESETFORE, SCE_RB_CHARACTER, RGB(128, 10, 128)); // 字符
SendEditor(SCI_STYLESETFORE, SCE_RB_CLASSNAME, RGB(0, 0, 255)); // 类名
SendEditor(SCI_STYLESETFORE, SCE_RB_DEFNAME, RGB(4, 153, 190)); // 定义名
SendEditor(SCI_STYLESETFORE, SCE_RB_OPERATOR, RGB(0, 0, 128)); // 操作符
SendEditor(SCI_STYLESETFORE, SCE_RB_IDENTIFIER, RGB(0, 0, 160)); // 标识符
SendEditor(SCI_STYLESETFORE, SCE_RB_REGEX, RGB(0, 20, 160)); // 正则表达式
SendEditor(SCI_STYLESETFORE, SCE_RB_GLOBAL, RGB(160, 0, 160)); // 全局变量
SendEditor(SCI_STYLESETFORE, SCE_RB_SYMBOL, RGB(223, 52, 52)); // 符号
SendEditor(SCI_STYLESETFORE, SCE_RB_MODULE_NAME, RGB(223, 52, 252)); // 模块名
SendEditor(SCI_STYLESETFORE, SCE_RB_INSTANCE_VAR, RGB(223, 152, 52)); // 实例变量
SendEditor(SCI_STYLESETFORE, SCE_RB_CLASS_VAR, RGB(23, 152, 52)); // 类变量
// 设置折叠
SendEditor(SCI_SETTABWIDTH, 4);
SendEditor(SCI_SETPROPERTY, (sptr_t)"fold", (sptr_t)"1");
SendEditor(SCI_SETMARGINCURSORN, MARGIN_FOLD_INDEX, SC_CURSORARROW);
// 折叠标签样式
SendEditor(SCI_SETMARGINTYPEN, MARGIN_FOLD_INDEX, SC_MARGIN_SYMBOL);// 页边类型
SendEditor(SCI_SETMARGINMASKN, MARGIN_FOLD_INDEX, SC_MASK_FOLDERS); // 页边掩码
SendEditor(SCI_SETMARGINWIDTHN, MARGIN_FOLD_INDEX, 11); // 页边宽度
SendEditor(SCI_SETMARGINSENSITIVEN, MARGIN_FOLD_INDEX, TRUE); // 响应鼠标消息
// 折叠标志 XPM
SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDER, SC_MARK_PIXMAP);
SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDEROPEN, SC_MARK_PIXMAP);
SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDEREND, SC_MARK_PIXMAP);
SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDEROPENMID, SC_MARK_PIXMAP);
SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_TCORNERCURVE);
SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDERSUB, SC_MARK_VLINE);
SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDERTAIL, SC_MARK_LCORNERCURVE);
//
SendEditor(SCI_MARKERDEFINEPIXMAP, SC_MARKNUM_FOLDER, (sptr_t)plus_xpm);
SendEditor(SCI_MARKERDEFINEPIXMAP, SC_MARKNUM_FOLDEROPEN, (sptr_t)minus_xpm);
SendEditor(SCI_MARKERDEFINEPIXMAP, SC_MARKNUM_FOLDEREND, (sptr_t)plus_xpm);
}
}
}
return callptr;
}
// Sci 窗口过程
LRESULT WINAPI SCIWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case SCI_STYLESETFONT:
{
break;
}
}
return ::CallWindowProc(g_pfnWndProc, hWnd, uMsg, wParam, lParam);
}
// Sci 父窗口过程
LRESULT WINAPI SCIParentWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if ((uMsg == WM_NOTIFY) && (lParam != NULL))
{
NMHDR * lnmhdr = (NMHDR*)lParam;
if (lnmhdr->hwndFrom == g_hSCIWnd)
{
SCNotification * lSCNmhdr = (SCNotification*)lParam;
switch (lnmhdr->code)
{
case SCN_STYLENEEDED:
case SCN_CHARADDED:
case SCN_SAVEPOINTREACHED:
case SCN_SAVEPOINTLEFT:
case SCN_MODIFYATTEMPTRO:
case SCN_DOUBLECLICK:
case SCN_UPDATEUI:
case SCN_MODIFIED:
case SCN_MACRORECORD:
break;
case SCN_MARGINCLICK: /// 旁注栏被单击
{
SendEditor(SCI_TOGGLEFOLD, SendEditor(SCI_LINEFROMPOSITION, lSCNmhdr->position));
break;
}
}
}
}
return ::CallWindowProc(g_pfnParentWndProc, hWnd, uMsg, wParam, lParam);
}[/pre]
当然这个很简单。
我脱壳 RMXP 后 用 OD 逆向 IDA 辅助 逆向出了以下代码
RGSSGetInt("$data_scripts.size") // 取脚本数量
RGSSGetStringACP (“$data_scripts ”) // 取指定脚本名称
RGSSGetStringUTF8 (“Zlib::Inflate.inflate($data_scripts )”) // 解码脚本
可以说 在内部, 脚本是用 RUBY 进行保存的。
说说自动完成吧,问题就在这里,如果这个成功了。我也不会放弃。
在我编写脚本分析器 困难重重,首先 我学到编程 脚本 太多 乱。个人能力不行,
参考了很多开源的 RUBY IDE 中,
很多人都说 RUBY 很多变量 类型 是要在运行后才能确定 所以词法 语法分析 没有一定功力是无法完成的,我这里也只写了一点点
[pre lang="c++" line="0"]
// 跳过注释
int WINAPI seek_remark(char * str, int len)
{
do
{
switch (*str++)
{
case '#':
{
char * s = str;
do
{
char chr = *s++;
switch (chr)
{
case '\r':
return (*s == '\n')?(int(s) - int(str) + 2):(int(s) - int(str) + 1);
case '\n':
case '\0':
return int(s) - int(str) + 1;
default:
{
if (isHighBitChar(chr))
s++;
break;
}
}
} while (1);
}
case '=':
{
// =begin=end
if (_PINT(str) == REMARK_BEGIN_DWORD) // 0 1 2 3
{
str += sizeof(DWORD);
if (*str++ == 'n')
{
int i = _strstr(str, "=end", len - 6, 4);
return (i != -1)?(10+i):len;
}
}
return 0;
}
}
} while (1);
return 0;
}
// 解析到下个字符串包围壳
int parsing_string_symbol(char * str, char symbol)
{
char * s = str;
do
{
char c = *s++;
if (c == symbol)
return (int)(s - str);
else if (c == '\\') // 忽略下个符号
s += isHighBitChar(*s)?2:1;
else if (isHighBitChar(c))
s++;
} while (1);
return 0;
}
// 解析数值
int parsing_num(char * str)
{
char * s = str;
do
{
switch (*s++)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
{
break;
}
default:
return (int(s - str));
}
} while (1);
return 0;
}
// 寻文本 sunday 算法
int _strstr(char * src, char * des, int len_s, int len_d)
{
// if (len_d == 0) len_d = _strlen(des);
int i = 0;
int j = 0;
int pe = len_d - 1;
int tb = i;
int te = len_s - 1;
while ((i < len_s) && (j < len_d))
{
if (src == des[j])
{
i++;
j++;
}
else
{
int k = len_d - 1;
while (k >= 0 && src[pe + 1] != des[k])
{
k--;
}
int gap = len_d - k;
i += gap;
pe = i + len_d - 1;
tb = i;
j = 0;
}
}
if (i <= len_s)
{
return tb;
}
return -1;
}[/pre]
我也想过用 ctags 生成 tag list 可惜在 ctags 在 ruby 分析中 类 实例变量 与 全局变量 都无法分析出。⊙﹏⊙!算了 说多了,都是泪。 |
|