[toc]

x86程序中的写法

1. ce寻找MessageoxA函数地址并通过自动汇编调用MessageBoxA

  1. 打开CE,附加程序

  2. 搜索MessageBoxA的地址

  3. 编写自动汇编代码调用MessgeBoxA

写法1:使用push传递参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[ENABLE]
Alloc(newaddr,100)
createThreadAndWait(newaddr)

newaddr:
push 0
push 0
push 0
push 0
call 7714B730
ret


[DISABLE]
dealloc(newaddr)
//Auto Assembler Commands
//https://wiki.cheatengine.org/index.php?title=Auto_Assembler:Commands

写法2:使用push传递参数并保存ebp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[ENABLE]
Alloc(newaddr,100)
createThreadAndWait(newaddr)

newaddr:
push ebp
mov ebp,esp
push 0
push 0
push 0
push 0
call 7714B730
pop ebp
ret


[DISABLE]
dealloc(newaddr)
//Auto Assembler Commands
//https://wiki.cheatengine.org/index.php?title=Auto_Assembler:Commands

写法3:分配栈空间传递参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[ENABLE]
Alloc(newaddr,100)
createThreadAndWait(newaddr)

newaddr:
sub esp,10
call 7714B730
ret

[DISABLE]
dealloc(newaddr)
//Auto Assembler Commands
//https://wiki.cheatengine.org/index.php?title=Auto_Assembler:Commands

写法4:分配并使用1个栈空间传递参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[ENABLE]
Alloc(newaddr,100)
createThreadAndWait(newaddr)

newaddr:
mov [esp-4],2
sub esp,4
push 0
push 0
push 0
call 7714B730
ret


[DISABLE]
dealloc(newaddr)
//Auto Assembler Commands
//https://wiki.cheatengine.org/index.php?title=Auto_Assembler:Commands

写法5:分配并使用2个栈空间传递参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[ENABLE]
Alloc(newaddr,100)
createThreadAndWait(newaddr)

newaddr:
sub esp,8
mov [esp+4],2
mov [esp+0],0
push 0
push 0
call 7714B730
ret


[DISABLE]
dealloc(newaddr)
//Auto Assembler Commands
//https://wiki.cheatengine.org/index.php?title=Auto_Assembler:Commands

写法6:分配并使用3个栈空间传递参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[ENABLE]
Alloc(newaddr,100)
createThreadAndWait(newaddr)

newaddr:
sub esp,C
mov [esp+8],2
mov [esp+4],0
mov [esp+0],0
push 0
call 7714B730
ret


[DISABLE]
dealloc(newaddr)
//Auto Assembler Commands
//https://wiki.cheatengine.org/index.php?title=Auto_Assembler:Commands

写法6:分配并使用栈空间传递所有参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[ENABLE]
Alloc(newaddr,100)
createThreadAndWait(newaddr)

newaddr:
sub esp,10
mov [esp+C],2
mov [esp+8],0
mov [esp+4],0
mov [esp],0
call 7714B730
ret


[DISABLE]
dealloc(newaddr)
//Auto Assembler Commands
//https://wiki.cheatengine.org/index.php?title=Auto_Assembler:Commands

写法7:分配并使用栈空间传递所有参数后平栈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[ENABLE]
Alloc(newaddr,100)
createThreadAndWait(newaddr)

newaddr:
sub esp,20
mov [esp+C],2
mov [esp+8],0
mov [esp+4],0
mov [esp],0
call 7714B730
add esp,10
ret


[DISABLE]
dealloc(newaddr)
//Auto Assembler Commands
//https://wiki.cheatengine.org/index.php?title=Auto_Assembler:Commands

2. 加载动态链接库调用MessageBoxA函数

1. 使用内联汇编

  • 创建动态链接库项目

    dllamin.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// dllmain.c : Defines the entry point for the DLL application.
#include <windows.h>

void AsmMessageBoxA()
{
HANDLE handle = NULL;
const char* Text = "Hello,World";
const char* Title = "Inline";
int style = MB_OK;
__asm {
push style
push Title
push Text
push handle
mov edx, MessageBoxA
call edx
}
}

BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
AsmMessageBoxA();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
  • 使用C语言程序加载动态链接库

    main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//Message.c
#include <stdio.h>
#include <Windows.h>

BOOL Load(DWORD dwProcessID, const WCHAR* szPath)
{
//LoadLibrary
//CreateRemoteThread
//1.打开目标进程获取句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID);
//2.在目标进程体内申请空间
LPVOID lpAddress = VirtualAllocEx(hProcess, NULL, 0x100, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
//3.写入DLL路径
SIZE_T sWriteLength = 0;
BOOL bRet = WriteProcessMemory(hProcess, lpAddress, szPath, ((wcslen(szPath) + 1) * 2), &sWriteLength);
if (bRet == FALSE)
{
MessageBoxW(NULL, L"WriteProcessMemory Failed!", L"Error", MB_OK);
}
//4.创建远程线程,执行回调
HANDLE hThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryW, lpAddress, NULL, NULL);
//5.等待远程线程执行结束(LoadLibrary返回了)
WaitForSingleObject(hThread, INFINITE);
//6.释放空间
VirtualFreeEx(hProcess, lpAddress, 0, MEM_RELEASE);
//7.释放句柄
CloseHandle(hProcess);
CloseHandle(hThread);
//8.返回结果
return TRUE;
}
int main()
{
//传入的两个参数分别为进程id与dll的绝对路径
Load(17948, L"D:\\test\\CC++\\c生万物之windows程序开发\\C+windows\\Debug\\Dll1.dll");
system("pause");
return 0;
}

2.在动态链接库中将汇编代码单独写在am文件中

  • 动态库完整代码

    dllmain.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // dllmain.c : Defines the entry point for the DLL application.
    #include <windows.h>
    //extern int AsmMessageBoxA_(void* paddr);
    DWORD paddr = 0x7714B730;

    BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved
    )
    {
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    AsmMessageBoxA_(paddr);
    break;
    case DLL_THREAD_ATTACH:
    break;
    case DLL_THREAD_DETACH:
    break;
    case DLL_PROCESS_DETACH:
    break;
    }
    return TRUE;
    }

    DllAsmMessage.asm

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    ;AsmMessage.asm
    .586
    .model flat,stdcall,c
    option casemap:none

    .data
    text db 'Load Dll success',0

    .code
    AsmMessageBoxA_ proc
    mov ebx,[esp+4]; eax = 'paddr'
    push 2
    push 0
    lea ecx,text
    push ecx
    push 0
    call ebx
    ret
    AsmMessageBoxA_ endp
    end

  • C语言加载动态库代码同上

x86_64位中的写法

1. ce寻找MessageoxA函数地址并通过自动汇编调用MessageBoxA

ce64位写法1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[ENABLE]
Alloc(newaddr,100)
createThreadAndWait(newaddr)

newaddr:
sub rsp,28
xor r9,r9
xor r8,r8
xor rdx,rdx
xor rcx,rcx
mov rax,7FFCC35EABD0
call rax
add rsp,28
ret


[DISABLE]
dealloc(newaddr)
//Auto Assembler Commands
//https://wiki.cheatengine.org/index.php?title=Auto_Assembler:Commands

ce64位写法2使用push入栈,使用add rsp,20平栈:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[ENABLE]
Alloc(newaddr,100)
createThreadAndWait(newaddr)

newaddr:
push rbp
mov rbp,rsp
push 0
push 0
push 0
push 0
mov rax,7FFCC35EABD0
call rax
add rsp,20
pop rbp
ret


[DISABLE]
dealloc(newaddr)
//Auto Assembler Commands
//https://wiki.cheatengine.org/index.php?title=Auto_Assembler:Commands

2. 加载动态链接库调用MessageBoxA函数

1. x86_64位中masm不支持内联汇编只能将汇编代码单独写在一个文件中

  • x86_64位动态库完整代码

    dllmain.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // dllmain.c : Defines the entry point for the DLL application.
    #include <windows.h>
    int AsmMessageBoxA_(void* paddr);
    DWORD64 paddr = 0x00007FFCC35EABD0;

    BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved
    )
    {
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    AsmMessageBoxA_(paddr);
    break;
    case DLL_THREAD_ATTACH:
    break;
    case DLL_THREAD_DETACH:
    break;
    case DLL_PROCESS_DETACH:
    break;
    }
    return TRUE;
    }

    DllAsmMessage.asm

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    ; AsmMessage.asm
    .data
    text db 'Load Dll success', 0

    .code
    AsmMessageBoxA_ proc
    mov rbx, rcx; rcx = 'paddr'
    sub rsp, 28h
    mov r9, 2
    mov r8, 0
    lea rdx, text
    mov rcx, 0
    call rbx
    add rsp, 28h
    ret
    AsmMessageBoxA_ endp
    end

    x86_64位C语言加载动态库

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//Message.c
#include <stdio.h>
#include <Windows.h>

BOOL Load(DWORD dwProcessID, const WCHAR* szPath)
{
//LoadLibrary
//CreateRemoteThread
//1.打开目标进程获取句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID);
//2.在目标进程体内申请空间
LPVOID lpAddress = VirtualAllocEx(hProcess, NULL, 0x100, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
//3.写入DLL路径
SIZE_T sWriteLength = 0;
BOOL bRet = WriteProcessMemory(hProcess, lpAddress, szPath, ((wcslen(szPath) + 1) * 2), &sWriteLength);
if (bRet == FALSE)
{
MessageBoxW(NULL, L"WriteProcessMemory Failed!", L"Error", MB_OK);
}
//4.创建远程线程,执行回调
HANDLE hThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryW, lpAddress, NULL, NULL);
//5.等待远程线程执行结束(LoadLibrary返回了)
WaitForSingleObject(hThread, INFINITE);
//6.释放空间
VirtualFreeEx(hProcess, lpAddress, 0, MEM_RELEASE);
//7.释放句柄
CloseHandle(hProcess);
CloseHandle(hThread);
//8.返回结果
return TRUE;
}
int main()
{
//传入的两个参数分别为进程id与dll的绝对路径
Load(17948, L"D:\\test\\CC++\\c生万物之windows程序开发\\C+windows\\Debug\\Dll1.dll");
system("pause");
return 0;
}