[toc]

用C语言写一个x86内联汇编程序

1. 用C语言写一个程序,内容为调用MessageBoxA函数

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//Message.c
#include <windows.h>
#include <stdio.h>

int main(int argc, char** argv)
{
printf("0x%p", &MessageBoxA);
MessageBoxA(NULL, "HellWorld", "Text", MB_OK);
MSG msg;
while (GetMessageW(&msg, NULL, NULL, NULL))
{
}
return 0;
}

结果如图所示:

Messagewithc

2. 用C语言与x86内联汇编写一个程序,内容为调用MessageBoxA函数

完整代码

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

#include <windows.h>
#include <stdio.h>

void AsmMessageBoxA()
{
__asm {
push 0
push 0
push 0
push 0
mov edx, 0x7515B730
call edx
}
}
int main(int argc, char** argv)
{
printf("MessageBoxA address is 0x%p\n", &MessageBoxA);
printf("AsmMessageBoxA() address is 0x%p\n", &AsmMessageBoxA);
AsmMessageBoxA();
MSG msg;
while (GetMessageW(&msg, NULL, NULL, NULL))
{

}
return 0;
}


结果如图所示:

AsmMessageAwithc

3. 用C语言与x86内联汇编写一个程序,内容为使用内联汇编调用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

#include <windows.h>
#include <stdio.h>

void Message()
{
MessageBoxA(NULL, "HellWorld", "Text", MB_OK);
}
void AsmMessage()
{
__asm {
mov edx, 0x0041140B //0x0041140B is Message() address
call edx
}
}
int main(int argc, char** argv)
{
printf("MessageBoxA address is 0x%p\n", &MessageBoxA);
printf("Message() address is 0x%p\n", &Message);
AsmMessage();
MSG msg;
while (GetMessageW(&msg, NULL, NULL, NULL))
{

}
return 0;
}


结果如图所示:

AsmMessage

4.用C语言与x86内联汇编写一个程序,使用内联汇编调用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

#include <windows.h>
#include <stdio.h>

void Message()
{
MessageBoxA(NULL, "HellWorld", "Text", MB_OK);
}
void AsmMessage(unsigned long addr)
{

__asm {
mov edx,addr //addr is Message() address
call edx
}
}
int main(int argc, char** argv)
{
printf("MessageBoxA address is 0x%p\n", &MessageBoxA);
printf("Message() address is 0x%p\n", &Message);
AsmMessage(&Message);
MSG msg;
while (GetMessageW(&msg, NULL, NULL, NULL))
{

}
return 0;
}

结果如图所示:

AsmMessageWithVar

5. 用C语言与x86内联汇编写一个程序,使用内联汇编调用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

#include <windows.h>
#include <stdio.h>

void Message()
{
MessageBoxA(NULL, "HellWorld", "Text", MB_OK);
}
void AsmMessage(void* paddr)
{
printf("paddr value is 0x%p\n", paddr);
__asm {
mov edx,[paddr] //addr is Message() address
call edx
}
}
int main(int argc, char** argv)
{
printf("MessageBoxA address is 0x%p\n", &MessageBoxA);
printf("Message() address is 0x%p\n", &Message);
AsmMessage(&Message);
MSG msg;
while (GetMessageW(&msg, NULL, NULL, NULL))
{
}
return 0;
}

结果如图所示:

AsmMessageWithPoint

6. 用C语言与x86内联汇编写一个程序,使用内联汇编调用MessageBoxA并传递参数

以下为完整代码:

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

#include <windows.h>
#include <stdio.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
}
}
int main(int argc, char** argv)
{
printf("MessageBoxA address is 0x%p\n", &MessageBoxA);
printf("AsmMessageBoxA() address is 0x%p\n", &AsmMessageBoxA);
AsmMessageBoxA();
MSG msg;
while (GetMessageW(&msg, NULL, NULL, NULL))
{
}
return 0;
}

结果如图所示:

AsmMessageWithParameters

7. 用C语言与x86内联汇编写一个程序,汇编指令与C语言代码分开引用

  1. 在项目中勾选Masm

  2. 新建一个文件命名为AsmMessage.asm

  3. 完整代码如下

    Message.asm

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

    .data
    .code
    AsmMessageBoxA_ proc
    mov eax,[esp+4]; eax = 'paddr'
    call eax
    ret
    AsmMessageBoxA_ endp
    end

    Message.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    //Message.c
    #include <windows.h>
    #include <stdio.h>

    extern int AsmMessageBoxA_(void* paddr);

    void Message()
    {
    MessageBoxA(NULL, "HellWorld", "Text", MB_OK);
    }

    int main(int argc, char** argv)
    {
    printf("MessageBoxA address is 0x%p\n", &MessageBoxA);
    printf("AsmMessageBoxA() address is 0x%p\n", &AsmMessageBoxA_);
    AsmMessageBoxA_(&Message);
    MSG msg;
    while (GetMessageW(&msg, NULL, NULL, NULL))
    {
    }
    return 0;
    }
  4. 运行结果如下:

AsmMessageWithAsm

8. 关于x86汇编的写法以及堆栈实验以下6个汇编程序堆栈完全平衡

1.[esp+4]为传过来的第一个参数,如果有二个参数,第二个参数应为[esp+8]

1
2
3
4
5
6
7
8
9
10
11
12
13
;AsmMessage.asm
.586
.model flat,c

.data
.code
AsmMessageBoxA_ proc
mov eax,[esp+4]; eax = 'paddr'
call eax
ret
AsmMessageBoxA_ endp
end

2. 使用push压入一个参数后需要将esp加4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
;AsmMessage.asm
.586
.model flat,c

.data
.code
AsmMessageBoxA_ proc
push ebp
mov eax,[esp+8]; eax = 'paddr'
call eax
add esp,4
ret
AsmMessageBoxA_ endp
end

3.pop一个寄存器等同于add esp,4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
;AsmMessage.asm
.586
.model flat,c

.data
.code
AsmMessageBoxA_ proc
push ebp
mov eax,[esp+8]; eax = 'paddr'
call eax
pop ebp
ret
AsmMessageBoxA_ endp
end

4.sub esp,4等同于push 一个寄存器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
;AsmMessage.asm
.586
.model flat,c

.data
.code
AsmMessageBoxA_ proc
push ebp
sub esp,10h
mov eax,[esp+18h]; eax = 'paddr'
call eax
add esp,14h

ret
AsmMessageBoxA_ endp
end

5.使用堆栈通过寄存器来赋值与取值

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

.data
.code
AsmMessageBoxA_ proc
sub esp,10h
mov ebx,10
mov [esp+12],ebx
mov [esp+8],ebx
mov [esp+4],ebx
mov [esp],ebx
mov eax,[esp+14h]; eax = 'paddr'
call eax
add esp,10h
ret
AsmMessageBoxA_ endp
end

6.push与pop指令可以操作堆空间

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
;AsmMessage.asm
.586
.model flat,c

.data
.code
AsmMessageBoxA_ proc
sub esp,10h
mov ebx,10
mov [esp+12],ebx
push [esp+12]
mov [esp+8],ebx
mov [esp+4],ebx
mov [esp],ebx
mov eax,[esp+18h]; eax = 'paddr'
call eax
pop [esp+12]
pop [esp]
pop [esp+4]
pop [esp+8]
add esp,4
ret
AsmMessageBoxA_ endp
end

9. c语言程序使用Naked函数内联x86汇编

完整代码

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
//Messageb.c
#include <windows.h>
#include <stdio.h>

void Message()
{
MessageBoxA(NULL, "HellWorld", "Text", MB_OK);
}
void __declspec(naked) MessageNaked(unsigned long* paddr)
{
__asm {
mov edx, [esp+4] //addr is Message() address
call edx
ret
}
}
int main(int argc, char** argv)
{
printf("MessageBoxA address is 0x%p\n", &MessageBoxA);
printf("Message() address is 0x%p\n", &Message);
printf("Current pid is %d\n",GetCurrentProcessId());
MessageNaked(&Message);
MSG msg;
while (GetMessageW(&msg, NULL, NULL, NULL))
{
}
return 0;
}

用C语言写一个x86_64内联汇编程序

1. 用C语言与x86内联汇编写一个程序,汇编指令与C语言代码分开引用

  1. 在项目中勾选Masm

  2. 新建一个文件命名为AsmMessage.asm

  3. 完整代码如下

    Message.asm

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ;Message.asm
    .data
    .code

    AsmMessageBoxA_ proc
    sub rsp,8h
    call rcx ;rcx = 'paddr'
    add rsp,8h
    ret
    AsmMessageBoxA_ endp
    end

    Message.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    //Message.c
    #include <windows.h>
    #include <stdio.h>

    extern int AsmMessageBoxA_(void* paddr);

    void Message()
    {
    MessageBoxA(NULL, "HellWorld", "Text", MB_OK);
    }

    int main(int argc, char** argv)
    {
    printf("MessageBoxA address is 0x%p\n", &MessageBoxA);
    printf("AsmMessageBoxA() address is 0x%p\n", &AsmMessageBoxA_);
    AsmMessageBoxA_(&Message);

    MSG msg;
    while (GetMessageW(&msg, NULL, NULL, NULL))
    {
    }
    return 0;
    }
  4. 运行成功

2.关于x64的堆栈平衡,以下3个程序堆栈完全平衡

1.使用push与pop指令平衡堆栈

1
2
3
4
5
6
7
8
9
10
;AsmMessage.asm
.data
.code
AsmMessageBoxA_ proc
push rcx
call rcx; rcx = 'paddr'
pop rcx
ret
AsmMessageBoxA_ endp
end

2.使用sub rsp,8h与pop指令平衡堆栈

1
2
3
4
5
6
7
8
9
10
11
;AsmMessage.asm
.data
.code
AsmMessageBoxA_ proc
sub rsp,8h
call rcx; rcx = 'paddr'
pop [rsp+8]
ret
AsmMessageBoxA_ endp
end

3. 使用全局变量保存数据并call两次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
;AsmMessage.asm
.data
paddr dq 0;
.code
AsmMessageBoxA_ proc
sub rsp,8h
mov paddr,rcx
call rcx; rcx = 'paddr'
mov rcx,paddr
call rcx; rcx = 'paddr'
add rsp,8h
ret
AsmMessageBoxA_ endp
end

3.在x86_64位汇编中写一个汇编调用MessageBoxA的程序

  • Message.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    //Message.c
    #include <windows.h>
    #include <stdio.h>

    int AsmMessageBoxA_(void* pAddr);

    int main(int argc, char** argv)
    {
    printf("0x%p", &MessageBoxA);
    MessageBoxA(NULL, "HellWorld", "Text", MB_OK);
    AsmMessageBoxA_(&MessageBoxA);
    MSG msg;
    while (GetMessageW(&msg, NULL, NULL, NULL))
    {
    }
    return 0;
    }

  • AsmMessage.asm

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    ; AsmMessage.asm
    .data
    text db 'Call MessageBoxA 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