- UID
- 8271
- 精华
- 积分
- 388
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
本帖最后由 Mat 于 2023-3-29 03:29 编辑
【原创】来源:https://www.0xaa55.com/thread-27352-1-1.html
转载请注明出处。
写汇编程序的麻烦之一就是怕定义的标号名、变量名以及过程名产生名称冲突,所以通常会做一些编码规范的约定,防止以上问题的产生。不过总觉得心理负担加重了,不能愉快的写代码。或者辛辛苦苦的编写了一个dll,导出了一些函数,但别人一看导出表导出的函数名称就大概能猜测出某个函数是干什么用的,会不会觉得很不爽?如果说中了各位的痛处,那就请继续往下看。
利用MASM的宏函数进行名称混淆,混淆的规则很简单,就是进行简单的字符映射,准备2张字符序列表:
- C_VARNAME_DEFAULT_ALPHABET EQU <abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPTRSTUVWXYZ0123456789_$?@>
- C_VARNAME_SHUFFLE_ALPHABET1 EQU <Yx4Om7LuN2XTI38S_wAtnalRhi1CcspFEoqzDGrBZ06gUHdeMKVvkTjJ5Pbf9Wy@$?>
复制代码
比如要将 Sub 进行混淆,则从第一张表中查找对应的索引,然后映射到第二张表中,就变成了:Unx,之后再附加指定的前缀,就妥了。
执行效果
可以看到,生成的TestDll.dll中导出表中的某些全局变量及函数名称已经混淆了:
以下是VarName.mac的实现:
- ;;=============================================================================
- ;;作者:Mat
- ;;网址:https://www.0xaa55.com/?8271
- ;;请保留原作者信息,否则视为侵权。
- ;;-----------------------------------------------------------------------------
- IFNDEF __VARNAME_MAC_
- __VARNAME_MAC_ EQU <1>
- IFNDEF VAR_NAME_PREFIX
- VAR_NAME_PREFIX TEXTEQU <VARNAME>
- ELSE
- IFIDN VAR_NAME_PREFIX, <>
- VAR_NAME_PREFIX TEXTEQU <VARNAME>
- ENDIF
- ENDIF
- ; private
- C_VARNAME_DEFAULT_ALPHABET EQU <abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPTRSTUVWXYZ0123456789_$?@>
- C_VARNAME_SHUFFLE_ALPHABET1 EQU <Yx4Om7LuN2XTI38S_wAtnalRhi1CcspFEoqzDGrBZ06gUHdeMKVvkTjJ5Pbf9Wy@$?>
- C_VARNAME_SHUFFLE_ALPHABET2 EQU <5irBYsdzMUakRcKg1IDE9C_vftmNeTbX6ZpyS3J7Hho2LGV08FAnqjux4lwTWPO?@$>
- ; private
- C_VARNAME_ALPHABET_INDEX_MIN EQU <1>
- C_VARNAME_ALPHABET_INDEX_MAX EQU @SizeStr(%C_VARNAME_DEFAULT_ALPHABET)
- ; private
- M_VARNAME_CharMapping MACRO chr:REQ, shuffleAlphabet
- LOCAL index
- index TEXTEQU @InStr(, %C_VARNAME_DEFAULT_ALPHABET, chr)
- IF index
- EXITM @SubStr(shuffleAlphabet, index, 1)
- ENDIF
- EXITM VAR_NAME_PREFIX
- ENDM
- ; public
- MVN MACRO varname:REQ
- LOCAL symname, chr
- symname TEXTEQU @CatStr(<_>, %VAR_NAME_PREFIX, <_>)
- % FOR num, <1,2>
- % FORC chr, varname
- symname TEXTEQU @CatStr(%symname, M_VARNAME_CharMapping(chr, %C_VARNAME_SHUFFLE_ALPHABET&num))
- ENDM
- ENDM
- symname TEXTEQU @CatStr(%symname, <_>, %(@SizeStr(%symname) - @SizeStr(%VAR_NAME_PREFIX) - 2), <_>)
- EXITM <symname>
- ENDM
- ;% ECHO Generate VarName: MVN(<gHello>)
- ENDIF
复制代码
只需要引入 VarName.mac,调用宏函数 MVN 即可。
但是有一个问题,就是如果用于 dll 的话,需要生成相应在的 .def 文件,这个我用 VBScript 实现了。Def.vbs 代码如下:
- '=============================================================================
- '作者:Mat
- '网址:https://www.0xaa55.com/?8271
- '请保留原作者信息,否则视为侵权。
- '-----------------------------------------------------------------------------
- Option Explicit
- Const DEFAULT_ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPTRSTUVWXYZ0123456789_$?@"
- Const SHUFFLE_ALPHABET1 = "Yx4Om7LuN2XTI38S_wAtnalRhi1CcspFEoqzDGrBZ06gUHdeMKVvkTjJ5Pbf9Wy@$?"
- Const SHUFFLE_ALPHABET2 = "5irBYsdzMUakRcKg1IDE9C_vftmNeTbX6ZpyS3J7Hho2LGV08FAnqjux4lwTWPO?@$"
- Const VAR_NAME_PREFIX = "VARNAME"
- Const ALPHABET_INDEX_MIN = 1
- Dim ALPHABET_INDEX_MAX: ALPHABET_INDEX_MAX = Len(DEFAULT_ALPHABET)
- Function CharMapping(char, shuffleAlphabet)
- Dim pos: pos = InStr(1, DEFAULT_ALPHABET, char, vbBinaryCompare)
- If pos = 0 Then
- CharMapping = VAR_NAME_PREFIX
- Else
- CharMapping = Mid(shuffleAlphabet, pos, 1)
- End If
- End Function
- Function StrMapping(vname, shuffleAlphabet)
- Dim symname: symname = ""
- Dim i
- For i = 1 To Len(vname) Step 1
- symname = symname & CharMapping(Mid(vname, i, 1), shuffleAlphabet)
- Next
- StrMapping = symname
- End Function
- Function VarName(vname, prefix)
- Dim strPrefix
- If IsEmpty(prefix) Or IsNull(prefix) Or prefix="" Then
- strPrefix = VAR_NAME_PREFIX
- Else
- strPrefix = prefix
- End If
- Dim symname: symname = "_" & strPrefix & "_"
- symname = symname & StrMapping(vname, SHUFFLE_ALPHABET1)
- symname = symname & StrMapping(vname, SHUFFLE_ALPHABET2)
- symname = symname & "_" & (Len(symname) - Len(strPrefix) - 2) & "_"
- VarName = symname
- End Function
- Dim fso: Set fso = CreateObject("Scripting.FileSystemObject")
- If WScript.Arguments.Count < 1 Then
- WScript.Echo "缺少参数:", Chr(13), Chr(10), Chr(9), "Usage: cscript Def.vbs <Dll Name>.def [VarName Prefix String]"
- WScript.Quit
- End If
- Dim strPrefix: strPrefix = ""
- If WScript.Arguments.Count > 1 Then
- strPrefix = Trim(WScript.Arguments(1))
- If Len(strPrefix) < 1 Then
- strPrefix = VAR_NAME_PREFIX
- End If
- End If
- Dim defFileName: defFileName = Trim(WScript.Arguments(0))
- If fso.FileExists(defFileName) Then
- fso.DeleteFile defFileName, True
- End If
- Const ForReading = 1, ForWriting = 2
- Dim defTplFile: Set defTplFile = fso.OpenTextFile("def.tpl", ForReading)
- Dim defFile: Set defFile = fso.OpenTextFile(defFileName, ForWriting, True)
- defFile.WriteLine "LIBRARY " & fso.GetBaseName(defFileName) & ".dll"
- defFile.WriteLine "EXPORTS"
- Do While Not defTplFile.AtEndOfStream
- Dim line: line = Trim(defTplFile.ReadLine)
- If line <> "" Then
- If Left(line, 1) = "!" Then
- line = Mid(line, 2)
- Else
- Dim i
- Dim strName: strName = ""
- Dim strChar
- For i = 1 To Len(line)
- strChar = Mid(line, i, 1)
- If strChar = " " Or strChar = "\t" Or strChar = "\r" Or strChar = "\n" Then Exit For
-
- strName = strName & strChar
- Next
- line = VarName(strName, strPrefix) & Mid(line, i)
- End If
- defFile.WriteLine Chr(9) & line
- End If
- Loop
- defTplFile.Close
- defFile.Close
- Set defTplFile = Nothing
- Set defFile = Nothing
- Set fso = Nothing
复制代码
事实上 Def.vbs 也实现了 VarName.mac 的混淆算法,在编译 dll 前,执行 Def.vbs 生成相应的模块定义文件 .def。Def.tpl 是用于生成 .def 的模板,用于定义导出的全局变量及函数,模板中以 ! 开头的名称表示不进行名称混淆,接下来进行编译:
- cscript /nologo Def.vbs $(DLL).def $(VAR_NAME_PREFIX)
复制代码
并且可以指定名称前缀,当然在编译的时候也同样需要指定,帖上 Makefile:
- NAME=Test
- OBJS=$(NAME).obj
- RES=$(NAME).res
- DLL=TestDll
- VAR_NAME_PREFIX=0x3f3f3f3f
- ML_FLAG=/nologo /c /coff /DVAR_NAME_PREFIX=$(VAR_NAME_PREFIX)
- LINK_FLAG=/nologo /subsystem:windows
- $(NAME).exe: $(OBJS) $(RES) $(DLL).obj $(DLL).dll
- link32 $(LINK_FLAG) /out:$(NAME).exe $(OBJS) $(RES)
- start $(NAME).exe
- VarNameDll.obj:
- ml $(ML_FLAG) $(DLL).asm
- .asm.dll:
- cscript /nologo Def.vbs $(DLL).def $(VAR_NAME_PREFIX)
- link32 $(LINK_FLAG) /dll /def:$(DLL).def $(DLL).obj
- .asm.obj:
- ml $(ML_FLAG) $<
- .rc.res:
- rc $<
- clean:
- del /q *.obj > nul 2>&1
- del /q *.pdb > nul 2>&1
- del /q *.ilk > nul 2>&1
- del /q *.lst > nul 2>&1
- del /q *.map > nul 2>&1
- del /q *.res > nul 2>&1
- del /q *.exp > nul 2>&1
- del /q *.lib > nul 2>&1
- del /q *.dll > nul 2>&1
- del /q *.exe > nul 2>&1
复制代码
用 nmake 进行编译:
接下来是写了下dll,并且在一个主模块中调用这个dll,代码很简单,就直接帖上来了。
TestDll.asm:
- .386
- .model flat, stdcall
- option casemap:none
- ;=============================================================================
- ;作者:Mat
- ;网址:https://www.0xaa55.com/?8271
- ;请保留原作者信息,否则视为侵权。
- ;-----------------------------------------------------------------------------
- include windows.inc
- include user32.inc
- includelib user32.lib
- include TestDll.inc
- public gTitle
- public MVN(<gHello>)
- public MVN(<gGoodBye>)
- .data
- gTitle BYTE 'VarName Test', 0
- MVN(<gHello>) BYTE 'Hello, World!', 0
- MVN(<gGoodBye>) BYTE 'Good Bye My Love!', 0
- .code
- DllMain PROC hinstDLL:HINSTANCE, fdwReason:DWORD, lpvReserved:LPVOID
- mov eax, TRUE
- ret
- DllMain ENDP
- MVN(<SayHello>) PROC STDCALL _lpTitle:PBYTE
- INVOKE MessageBox, NULL, ADDR MVN(<gHello>), _lpTitle, MB_OK
- ret
- MVN(<SayHello>) ENDP
- _SayGoodBye PROC STDCALL _lpMessage:PBYTE
- INVOKE MessageBox, NULL, _lpMessage, ADDR gTitle, MB_OK
- ret
- _SayGoodBye ENDP
- end DllMain
复制代码
Test.asm:
- .386
- .model flat, stdcall
- option casemap:none
- ;=============================================================================
- ;作者:Mat
- ;网址:https://www.0xaa55.com/?8271
- ;请保留原作者信息,否则视为侵权。
- ;-----------------------------------------------------------------------------
- include windows.inc
- include kernel32.inc
- include user32.inc
- include msvcrt.inc
- includelib kernel32.lib
- includelib user32.lib
- includelib msvcrt.lib
- include Test.inc
- includelib TestDll.lib
- .data
- hDllInstance HINSTANCE 0
- .code
- start:
- INVOKE GetModuleHandle, M_TEXT(<TestDll>)
- mov hDllInstance, eax
- ; SayHello
- INVOKE GetProcAddress, hDllInstance, M_TEXT(<gTitle>)
- INVOKE MVN(<SayHello>), eax
- ; _SayGoodBye
- INVOKE GetProcAddress, hDllInstance, M_TEXT(%MVN(<gGoodBye>))
- INVOKE _SayGoodBye, eax
- INVOKE ExitProcess, NULL
- end start
复制代码
VarName.zip
(4.8 KB, 下载次数: 1, 售价: 2 个宅币)
|
|