[toc]

C语言通过内联汇编隐藏函数调用

1. 通过C语言内联汇编隐藏调用函数,将需要调用的地址放到[ebp+4]的位置(此程序执行成功,但会堆栈不平衡造成程序崩溃)

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


#pragma optimize("",off)
void empty()
{
printf("1:empty\n");
}

int main()
{
_asm {
mov eax, empty
mov [ebp + 4], eax
}

printf("2:stack\n");
}

#pragma optimize("",on)

2.通过C语言裸函数内联汇编隐藏调用函数,将需要调用的地址放到[ebp+4]的位置,使用[ebp+4]的值前将[ebp+4]的值赋予[ebp+8]

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>


#pragma optimize("",off)
void empty()
{
printf("1:empty\n");
}
void _declspec(naked) stack()
{
__asm {
mov ebx,[ebp+4]
mov [ebp+8],ebx
mov eax, [empty] // 假设 empty 是一个有效的变量
mov [ebp+4] , eax // 将 eax 的值存储到调用者的堆栈中
ret
}
}
int main()
{
stack();
printf("2:stack\n");
}

#pragma optimize("",on)

3.通过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>


#pragma optimize("",off)
void empty()
{
printf("1:empty\n");
}
void stack()
{
__asm {
mov ebx, [ebp+4]
mov eax, [empty] // 假设 empty 是一个有效的变量
mov [ebp+4], eax // 将 eax 的值存储到调用者的堆栈中
mov [ebp+8], ebx
}
}
int main()
{
stack();
_asm sub esp,4
printf("2:stack\n");
}

#pragma optimize("",on)

4.通过C语言内联x86_64位汇编隐藏调用函数(需要intel或者LLVM编译器,Debug模式下也可成功)

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

#pragma optimize("", off)
void empty()
{
printf("1:empty\n");
}

void stack()
{

__asm {
push rbp // 保存旧的基指针
mov rbp, rsp // 设置新的基指针

// 获取 empty 函数的地址
lea rax, empty // 使用 lea 加载 empty 函数的地址
mov [rbp+8], rax // 将 empty 的地址存储到调用者的堆栈中

// 恢复堆栈
mov rsp, rbp // 恢复堆栈指针
pop rbp // 恢复旧的基指针
ret
}
}

int main()
{
int i = 0;

stack();
printf("2:stack\n");
}

#pragma optimize("", on)

5.通过C语言裸函数内联x86_64位汇编隐藏调用函数(需要intel编译器,Debug模式下也可成功)

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
39
40
#include <windows.h>
#include <stdio.h>

#pragma optimize("", off)
void empty()
{
printf("1:empty\n");
}

void _declspec(naked) stack()
{



__asm {
push 0
push rbp // 保存旧的基指针
mov rbp, rsp // 设置新的基指针

// 获取 empty 函数的地址
lea rax, empty // 使用 lea 加载 empty 函数的地址
mov[rbp + 8], rax // 将 empty 的地址存储到调用者的堆栈中

// 恢复堆栈
mov rsp, rbp // 恢复堆栈指针
pop rbp // 恢复旧的基指针
ret
}
}

int main()
{
int i = 0;

stack();
printf("2:stack\n");
}

#pragma optimize("", on)

C语言通过数组越界隐藏函数调用

1.C语言在主函数中隐藏调用自写函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <windows.h>
#include <stdio.h>
#pragma warning (disable: 4789)

#pragma optimize("",off)
void empty()
{
printf("1:empty\n");
}

int main()
{
int ary[1];
ary[3] = ary[2];
ary[2] = (int)empty;
printf("2:stack\n");
}

#pragma optimize("",on)

2.C语言在其他函数中隐藏调用自写函数,通过push指令平栈

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


#pragma optimize("",off)
void empty()
{
printf("1:empty\n");
}

void stack()
{
int ary[1];
ary[3] = ary[2];
ary[2] = (int)empty;
printf("2:stack\n");
}
int main()
{
_asm push 0
stack();
printf("3:main\n");
}

#pragma optimize("",on)

3. 在其他函数中隐藏调用MessageBoxA函数,通过sub esp指令平栈

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


#pragma optimize("",off)

void stack()
{
int ary[2];
ary[4] = ary[3];
ary[3] = (int)MessageBoxA;
ary[5] = 0;
ary[6] = (int)"aaaaaaa";
ary[7] = (int)"BBBBBB";
ary[8] = 2;
printf("1:stack\n");
}
int main()
{
_asm sub esp,0x14
stack();
printf("2:main\n");
}

#pragma optimize("",on)

4.通过函数指针隐藏调用函数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
31
32
33
34
35
#include <windows.h>
#include <stdio.h>
#include <conio.h>


#pragma optimize("",off)

void hidefunc()
{
int ary[1];
ary[2] = ary[2] ^ ary[3];
ary[3] = ary[2] ^ ary[3];
ary[2] = ary[2] ^ ary[3];
}
typedef int* (WINAPI *Ph_MessageBoxA)(void *address,
_In_opt_ HWND hWnd,
_In_opt_ LPCSTR lpText,
_In_opt_ LPCSTR lpCaption,
_In_ UINT uType);
typedef HANDLE (WINAPI *Ph_OpenProcess)(void* address,
_In_ DWORD dwDesiredAccess,
_In_ BOOL bInheritHandle,
_In_ DWORD dwProcessId
);
int main()
{
((Ph_MessageBoxA)hidefunc)(MessageBoxA, 0, 0, 0, 1);
DWORD dwProcessId = GetCurrentProcessId();
HANDLE handle=((Ph_OpenProcess)hidefunc)(OpenProcess, PROCESS_ALL_ACCESS, FALSE, dwProcessId);
printf("%d",handle);

return 0;
}
#pragma optimize("",on)

5.通过隐藏函数调用创建远程线程加载MessageBoxA(可过某些杀毒软件)

  1. main.c

    1
    2
    3
    4
    5
    6
    7
    8
    //main.c
    #include "shellcode.h"

    int main(int argc, char** argv)
    {
    InjectCode(54724, AddSun);
    return 0;
    }
  2. DefineHide.

    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    //DefineHide.
    #pragma once
    #include <windows.h>

    typedef int* (WINAPI* hMessageBoxA)(void* address,
    _In_opt_ HWND hWnd,
    _In_opt_ LPCSTR lpText,
    _In_opt_ LPCSTR lpCaption,
    _In_ UINT uType);
    typedef HANDLE(WINAPI* hOpenProcess)(void* address,
    _In_ DWORD dwDesiredAccess,
    _In_ BOOL bInheritHandle,
    _In_ DWORD dwProcessId
    );

    typedef
    LPVOID
    (WINAPI*
    hVirtualAllocEx)(
    _In_ HANDLE hProcess,
    _In_opt_ LPVOID lpAddress,
    _In_ SIZE_T dwSize,
    _In_ DWORD flAllocationType,
    _In_ DWORD flProtect
    );

    typedef
    BOOL
    (WINAPI*
    hWriteProcessMemory)(
    _In_ HANDLE hProcess,
    _In_ LPVOID lpBaseAddress,
    _In_reads_bytes_(nSize) LPCVOID lpBuffer,
    _In_ SIZE_T nSize,
    _Out_opt_ SIZE_T * lpNumberOfBytesWritten
    );


    typedef
    HANDLE
    (WINAPI*
    hCreateRemoteThread)(
    _In_ HANDLE hProcess,
    _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
    _In_ SIZE_T dwStackSize,
    _In_ LPTHREAD_START_ROUTINE lpStartAddress,
    _In_opt_ LPVOID lpParameter,
    _In_ DWORD dwCreationFlags,
    _Out_opt_ LPDWORD lpThreadId
    );

    typedef
    DWORD
    (WINAPI*
    hWaitForSingleObject)(
    _In_ HANDLE hHandle,
    _In_ DWORD dwMilliseconds
    );

    typedef
    BOOL
    (WINAPI*
    hVirtualFreeEx)(
    _In_ HANDLE hProcess,
    _Pre_notnull_ _When_(dwFreeType == MEM_DECOMMIT, _Post_invalid_) _When_(dwFreeType == MEM_RELEASE, _Post_ptr_invalid_) LPVOID lpAddress,
    _In_ SIZE_T dwSize,
    _In_ DWORD dwFreeType
    );

    typedef
    BOOL
    (WINAPI*
    hCloseHandle)(
    _In_ _Post_ptr_invalid_ HANDLE hObject
    );

  3. shellcode.h

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #pragma once
    #include <windows.h>

    typedef struct tagParamCall
    {
    void* addr;
    HWND hWnd;
    char Text[MAXCHAR];
    char Caption[MAXCHAR];
    UINT uType;

    }ParamCall, * PParamCall;

    void AddSun(PParamCall Addr);
    void InjectCode(DWORD dwProcId, LPVOID mFunc);
    void hidefunc();
  4. shellcode.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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58

    #include "shellcode.h"
    #include <stdio.h>
    #include <conio.h>
    #include "DefineHide.h"

    void AddSun(PParamCall Addr)
    {
    int uType = Addr->uType;
    const char* Caption = Addr->Caption;
    DWORD* addr = Addr->addr;
    _asm {
    mov edx, [addr]
    push uType
    push Caption
    push 0
    push 0
    call edx

    }
    }
    void InjectCode(DWORD dwProcId, LPVOID mFunc)
    {
    HANDLE hProcess, hThread;
    LPVOID mFuncAddr, mParamAddr;
    DWORD NumberOfByte;

    hProcess = ((hOpenProcess)hidefunc)(OpenProcess, PROCESS_ALL_ACCESS, FALSE, dwProcId);

    mFuncAddr = ((hVirtualAllocEx)hidefunc)(VirtualAllocEx,hProcess, NULL, 1024, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    ((hWriteProcessMemory)hidefunc)(WriteProcessMemory,hProcess, mFuncAddr, mFunc, 1024, &NumberOfByte);
    ParamCall mParam;
    mParam.addr = &MessageBoxA;
    mParam.hWnd = NULL;
    memcpy(mParam.Text, "Text", strlen("Text"));
    memcpy(mParam.Caption, "title", strlen("title"));
    mParam.uType = 2;
    mParamAddr = ((hVirtualAllocEx)hidefunc)(VirtualAllocEx,hProcess, NULL, 1024, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    ((hWriteProcessMemory)hidefunc)(WriteProcessMemory,hProcess, mParamAddr, &mParam, 1024, &NumberOfByte);
    hThread = ((hOpenProcess)hidefunc)(CreateRemoteThread,hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)mFuncAddr, mParamAddr, 0, &NumberOfByte);
    ((hWaitForSingleObject)hidefunc)(WaitForSingleObject,hThread, INFINITE);
    ((hVirtualFreeEx)hidefunc)(VirtualFreeEx,hProcess, mFuncAddr, 1024, MEM_RELEASE);
    ((hVirtualFreeEx)hidefunc)(VirtualFreeEx,hProcess, mParamAddr, 1024, MEM_RELEASE);
    ((hCloseHandle)hidefunc)(CloseHandle,hThread);
    ((hCloseHandle)hidefunc)(CloseHandle,hProcess);
    }

    #pragma optimize("",off)
    void hidefunc()
    {
    int ary[1];
    ary[2] = ary[2] ^ ary[3];
    ary[3] = ary[2] ^ ary[3];
    ary[2] = ary[2] ^ ary[3];
    }
    #pragma optimize("",on)