从此淹没在我们时间的长河|

lockly

园龄:2年3个月粉丝:25关注:3

BOF编写-修改时间戳

模板配置

跟着网上的教程使用evilashz师傅的模板,下载模板解压至vs的模板目录:

%UserProfile%\Documents\Visual Studio 2022\Templates\ProjectTemplates

image

创建新项目选择刚刚新增的类型:Beacon Object File​。

image

环境适配

生成时报错,我使用的是2022版本的,模板有点老了他这里的是vs2019。

image

根据底下的提示从项目​ -> 重定目标解决方案​, 接着确定更新即可

image

但是一进来模板会报错没有引入库, 干脆就用最小测试代码:将 Source.cpp​重名为Source.c​并修改为如下:

#include <stdio.h>
#include <Windows.h>
#include "beacon.h"
void go(char* buff, int len) {
BeaconPrintf(CALLBACK_OUTPUT, "Hello BOF");
}

编译配置

在上方的生成中勾选BOF配置, 配置管理器的编译环境也一样的,就可以生成64位版本的。

image

但最好还是使用批生成同时生成32位和64位版本:生成​ -> 批生成​ 在BOF那两项勾选Win32​和x64​。

image

创建项目时没有勾选将解决方案和项目放在同一目录下​,那么生成的.obj​文件(编译未链接的目标文件)就在/bin/BOF​中。

image

测试如果用cs的话可以使用inline-execute E:\TARGET\timestamp.obj​。我这里执行成功但发现有乱码:

image

乱码问题

尝试了加上\n​换行来终止字符串刷新缓冲区但是不行,找到使用格式化输出宏的办法,将可变参数展开。比如这里的INFO_FORMAT("Hello BOF");​会被展开成BeaconPrintf(CALLBACK_OUTPUT, "[*] Hello BOF\n");​。

#include <stdio.h>
#include <Windows.h>
#include "beacon.h"
#define INFO_FORMAT(fmt, ...) BeaconPrintf(CALLBACK_OUTPUT, "[*] " fmt "\n", ##__VA_ARGS__)
void go(char* buff, int len) {
INFO_FORMAT("Hello BOF");
}

原先的内存中可能是这样:"Hello BOF" <未知内存内容>​,但使用宏之后就是这样的:"[*] Hello BOF\n" <确定的字符串终止>​,最后测试也没有乱码了。

image

功能实现

实现一个修改文件时间戳的功能, BOF不能直接调用Windows API, 而是通过cs提供的函数来交互。但我这里并不是为cs编写,所以要使用Windows API函数的话,首先需要进行声明:

Windows API声明

要修改文件时间戳, 就要用到SetFileTime​。它用于设置文件的创建时间、访问时间和修改时间。文档中原型如下:

BOOL SetFileTime(
[in] HANDLE hFile,
[in, optional] const FILETIME *lpCreationTime,
[in, optional] const FILETIME *lpLastAccessTime,
[in, optional] const FILETIME *lpLastWriteTime
);

  • hFile: 文件句柄,必须有FILE_WRITE_ATTRIBUTES访问权限
  • lpCreationTime: 文件的创建时间
  • lpLastAccessTime: 文件的最后访问时间
  • lpLastWriteTime: 文件的最后修改时间

那么在bof的声明中要注意这个函数是属于哪个dll, 比如这里是kernel32.dll​的话那要定义和调用它时就写成KERNEL32$SetFileTime​,完整如下:

DECLSPEC_IMPORT BOOL WINAPI KERNEL32$SetFileTime(HANDLE, const FILETIME*, const FILETIME*, const FILETIME*);

cs使用这种前缀可以让BOF直接调用DLL中的原生函数, 就不需要再在导入表中声明了,这样也可以缩小BOF体积。类似的使用CreateFileA​来创建或打开文件时, 其原型如下:

HANDLE CreateFileA(
[in] LPCSTR lpFileName, // 文件名
[in] DWORD dwDesiredAccess, // 访问模式
[in] DWORD dwShareMode, // 共享模式
[in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 安全描述符
[in] DWORD dwCreationDisposition, // 创建方式
[in] DWORD dwFlagsAndAttributes, // 文件属性
[in, optional] HANDLE hTemplateFile // 模板文件句柄
);

BOF中声明则如下:

DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$CreateFileA(LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);

以及其他要用到的api可以这样声明:

// 其他必要的API
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CloseHandle(HANDLE); // 关闭一个内核对象(如文件)的句柄
DECLSPEC_IMPORT VOID WINAPI KERNEL32$GetSystemTime(LPSYSTEMTIME); // 获取当前系统时间(UTC时间)
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$SystemTimeToFileTime(LPSYSTEMTIME, LPFILETIME); // 将SYSTEMTIME结构转换为FILETIME结构。

参数处理

BOF的入口函数就是这里的go, inline-execute​执行BOF时先调用这个。其中先定义并初始化一个解析器来解析传入的参数,timestamp​这个至少也是要一个参数路径的,先从一个来:

void go(char* buff, int len) {
datap parser;
char* filepath;
// 解析Beacon传入的参数
BeaconDataParse(&parser, buff, len);
filepath = BeaconDataExtract(&parser, NULL);
// 参数验证
if (!filepath) {
BeaconPrintf(CALLBACK_ERROR, "[-] please provide file path");
return;
}
}

那解析多个参数呢, 一样的:

BeaconDataParse(&parser, buff, len);
sourceFile = BeaconDataExtract(&parser, NULL);
targetFile = BeaconDataExtract(&parser, NULL);
if (!sourceFile || !targetFile) {
BeaconPrintf(CALLBACK_ERROR, "[!] Error: Two file paths required\n");
BeaconPrintf(CALLBACK_ERROR, "[-] Usage: inline-execute timestamp.o \"source_file\" \"target_file\"\n");
return;
}
BeaconPrintf(CALLBACK_OUTPUT, "[-] Source: %s\n", sourceFile);
BeaconPrintf(CALLBACK_OUTPUT, "[-] Target: %s\n", targetFile);

时间处理

接着继续,获取系统时间然后修改成我们希望的时间,比如2020年1月1日 00:00:00​。然后把他转换为文件时间格式:

SYSTEMTIME st;
FILETIME ft;
KERNEL32$GetSystemTime(&st);
st.wYear = 2020;
st.wMonth = 1;
st.wDay = 1;
st.wHour = 0;
st.wMinute = 0;
st.wSecond = 0;
KERNEL32$SystemTimeToFileTime(&st, &ft);

文件操作

准备好了要修改的时间后就尝试打开文件获取句柄:

HANDLE hFile = KERNEL32$CreateFileA(
filepath, // 文件路径
FILE_WRITE_ATTRIBUTES, // 只需要写属性权限
FILE_SHARE_READ | FILE_SHARE_WRITE, // 允许其他进程读写
NULL, // 默认安全属性
OPEN_EXISTING, // 只打开已存在的文件
FILE_ATTRIBUTE_NORMAL, // 使用标准属性
NULL // 不使用模板
);
if (hFile == INVALID_HANDLE_VALUE) {
BeaconPrintf(CALLBACK_ERROR, "[-] can not open file: %s", filepath);
return;
}

时间戳修改

最后使用SetFileTime​修改三个时间属性:创建时间、访问时间、修改时间。结束后关闭句柄。

if (!KERNEL32$SetFileTime(hFile, &ft, &ft, &ft)) {
BeaconPrintf(CALLBACK_ERROR, "[-] failed to change timestamp");
} else {
BeaconPrintf(CALLBACK_OUTPUT, "[+] success: %s", filepath);
}
KERNEL32$CloseHandle(hFile);

这样就简单完成了修改一个文件时间戳的功能,完整代码如下:

#include <stdio.h>
#include <Windows.h>
#include "beacon.h"
// 声明Windows API函数
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$SetFileTime(HANDLE, const FILETIME*, const FILETIME*, const FILETIME*);
DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$CreateFileA(LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CloseHandle(HANDLE);
DECLSPEC_IMPORT VOID WINAPI KERNEL32$GetSystemTime(LPSYSTEMTIME);
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$SystemTimeToFileTime(LPSYSTEMTIME, LPFILETIME);
void go(char* buff, int len) {
datap parser;
char* filepath;
BeaconDataParse(&parser, buff, len);
filepath = BeaconDataExtract(&parser, NULL);
if (!filepath) {
BeaconPrintf(CALLBACK_ERROR, "[-] please provide file path");
return;
}
SYSTEMTIME st;
FILETIME ft;
KERNEL32$GetSystemTime(&st);
st.wYear = 2020;
st.wMonth = 1;
st.wDay = 1;
st.wHour = 0;
st.wMinute = 0;
st.wSecond = 0;
KERNEL32$SystemTimeToFileTime(&st, &ft);
HANDLE hFile = KERNEL32$CreateFileA(
filepath,
FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE) {
BeaconPrintf(CALLBACK_ERROR, "[-] can not open file: %s", filepath);
return;
}
if (!KERNEL32$SetFileTime(hFile, &ft, &ft, &ft)) {
BeaconPrintf(CALLBACK_ERROR, "[-] failed to change timestamp");
}
else {
BeaconPrintf(CALLBACK_OUTPUT, "[+] sunccess: %s", filepath);
}
KERNEL32$CloseHandle(hFile);
}

测试

编译还是同上使用批生成,我这里测试的可以成功修改:

image

优化编译

为了更好的在苛刻环境下使用,我想继续压缩体积,找到的参数以及解释如下:

  • -Os: 优化大小(比-O2生成更小的代码)
  • -fno-asynchronous-unwind-tables: 禁用异常展开表
  • -fno-ident: 删除编译器版本信息
  • -fpack-struct=8: 结构体8字节对齐
  • -falign-functions=1: 函数1字节对齐
  • -s: 删除符号表
  • -ffunction-sections: 每个函数放入单独的段
  • -fdata-sections: 每个数据项放入单独的段
  • -fno-exceptions: 禁用异常处理
  • -fno-stack-protector: 禁用栈保护
  • -mno-stack-arg-probe: 禁用栈探测

64位使用的编译命令如下:

x86_64-w64-mingw32-gcc-8.1.0.exe -c .\Source.c -o timestamp.o -Os -fno-asynchronous-unwind-tables -fno-ident -fpack-struct=8 -falign-functions=1 -s -ffunction-sections -fdata-sections -fno-exceptions -fno-stack-protector -mno-stack-arg-probe

针对于编译32位版本的命令( 如果没有就用批生成, 重命名即可):

i686-w64-mingw32-gcc-8.1.0.exe -c .\Source.c -o timestamp.x86.o -Os -fno-asynchronous-unwind-tables -fno-ident -fpack-struct=8 -falign-functions=1 -s -ffunction-sections -fdata-sections -fno-exceptions -fno-stack-protector -mno-stack-arg-probe

注:这里生成的是.o而不是.obj只是自己的需求为了统一一下,obj是Windows平台的默认目标文件扩展名,而.o是Unix/Linux平台的扩展名。它们本质和功能上是一样的,只是命名习惯不同。

最后

这里只是简单的示例,要使用最好要有一个锚定文件,以他的时间作为目标来修改。细节不赘述,详细请跳转Github。最终版本的使用测试如下:

image

参考

本文作者:lockly

本文链接:https://www.cnblogs.com/bktown/p/18658793/bof-writingmodification-time-stamp-zgai05

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   lockly  阅读(125)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 过客 冯泳,HAIBEAT
  2. 2 Sorry But XMASwu(吴骜)
  3. 3 每当我 ProdbyMend
Sorry But - XMASwu(吴骜)
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : XMASwu(吴骜)

作曲 : XMASwu(吴骜)

编曲 : bezimeni

你是在拜佛

还是在拜

自己的欲望

想不明白

浪费着时光

躺着担心未来

出了点故障

想要从头再来

Life goes around

夜晚用来忘却所有受的伤

灰白色的荒野不停的turn around

默剧正在上演你到底要我怎么唱

Wanna see what I've become

Wanna see how bad I am now

Wanna see when I would cry

Wanna see me on the ground

Fake friends are leaving me

Real friends are little now

无所谓

Always feeling

I’m sorry I’m sorry I’m sorry

So Sorry for my mistake

regret it

I will change

You see me always ok

I’m ok

不会累

可是全部都是假的

我装的很像吗

血总滴在我心里面

这个世界会向阳开

我的生活定会圆满

我总是迷恋膝盖触碰腹部的安全感

我怕扑空

所以在衡量

这是我短板

夜晚摸着我的脉搏

跳动速率被你传染

我打开冰箱发现刚买的罐头竟然已经坏了

也他媽不奇怪了

都没关系

他们要你站得高还望得远

可我只想让你快乐

别让自己so tired

请别着急

可为什么我总学不会自己抬起头

那些消极情绪全部Go away

我也只有梦里牵过她的手

这种感觉 dont know how to say

朋友说我 do what I wanna do

别管别人Say what you wanna say

把自己包裹

像一个刺猬

Always feeling

I’m sorry I’m sorry I’m sorry

So Sorry for my mistake

regret it

I will change

You see me always ok

I’m ok

不会累

可是全部都是假的

我装的很像吗

血总滴在我心里面

Always feeling

I’m sorry I’m sorry I’m sorry

So Sorry for my mistake

regret it

I will change

You see me always ok

I’m ok

不会累

可是全部都是假的

我装的很像吗

血总滴在我心里面

我心里面

我心里面

和声 : 圣雨轻纱

混音 : 仔总裁

封面设计 : luoxi