bester 发表于 2019-7-11 19:23

36字节HOOK GetlocalTime 更改软件到期((附Delphi易语言双语言源码)

本帖最后由 bester 于 2019-7-11 19:31 编辑

原理说明:GetLocalTime(系统时间),他的这个参数是一个记录着系统时间的一个指针,我们只需要修改里面包含的时间,大小是16个字节
参数类型:
Delphi:
_SYSTEMTIME = record
    wYear: Word;//年
    wMonth: Word; //月
    wDayOfWeek: Word; //星期几
    wDay: Word; //日
    wHour: Word; //时
    wMinute: Word; //分
    wSecond: Word; //秒
    wMilliseconds: Word; //毫秒

易语言:
.数据类型 精易_时间, 公开, , SYSTEMTIME   
.成员 年, 短整数型, , "", wYear   
.成员 月, 短整数型, , "", wMonth
.成员 星期, 短整数型, , "",   
.成员 日, 短整数型, , "", wDay   
.成员 时, 短整数型, , "", wHour   
.成员 分, 短整数型, , "", wMinute
.成员 秒, 短整数型, , "", wSecond   
.成员 毫, 短整数型, , "", wMilliseconds   //短整数型=smallint 有符号16位,占2个字节,总共8个成员,所以8*2=16

ASMCode:
pushad                        //保护寄存器
pushfd                      //保护标志位
mov word ptr ss:, 0x7E2//年    7E2=2018年
mov word ptr ss:, 0x7 //月    7=7月
mov word ptr ss:, 0x4 //星期几 4=星期四
mov word ptr ss:, 0xB //日   B=11日,B的10进制是11
mov word ptr ss:, 0x11 // 时   11=17时,11的10进制是17
mov word ptr ss:, 0x21 //分    21=33分
mov word ptr ss:, 0x39 //秒    39=57秒
mov word ptr ss:, 0x48 //毫    48=72毫秒
popfd                     //恢复标志位
popad                     //恢复寄存器
retn                        //返回

Hex: 60 9C 66 36 C7 00 E2 07 66 36 C7 40 02 07 00 66 36 C7 40 04 04 00 66 36 C7 40 06 0B 00 66 36 C7 40 08 11 00 66 36 C7 40 0A 21 00 66 36 C7 40 0C 39 00 66 36 C7 40 0E 48 00 9D 61 C3   //word版本,每次写2个字节 转成汇编就是上面的代码Hex:60 9C 36 C7 00 E2 07 07 00 36 C7 40 04 04 00 0B 00 36 C7 40 08 11 00 21 00 36 C7 40 0C 39 00 48 00 9D 61 C3 //Dword版本,每次写入4个字节,效率较高,共36个字节
易语言源码:需要精益模块,写内存字节集=writeprocessmemory,因为懒得用精益的写法,花里胡哨,直接用的API函数.版本 2

.程序集 窗口程序集_启动窗口

.子程序 _按钮1_被单击
.局部变量 pid, 整数型
.局部变量 hprocess, 整数型
.局部变量 apiaddr, 整数型
.局部变量 Bsize, 整数型

pid = 进程_名取ID (“取现行时间.exe”, )
hprocess = 进程_打开1 (pid)
apiaddr = GetProcAddress (LoadLibraryA (“KernelBase.dll”), “GetLocalTime”)
写内存字节集 (hprocess, apiaddr, 字节集_还原 (“609C36C700E207070036C7400404000B0036C740081100210036C7400C390048009D61C3”), 36, Bsize)


.子程序 字节集_还原, 字节集, 公开, 将一串十六进制文本还原为字节集。还原为字节集可以将默认的16进制文本转换成字节集。如“00BFAD00”可还原为{0,191,173,0}
.参数 原始16进制文本, 文本型, , 如“00BFAD00AFD4FD4F9E054F9FF91FC5FF2076FBAFDB071044”
.局部变量 字节集, 字节集
.局部变量 次数, 整数型
.局部变量 临时变量, 整数型

.变量循环首 (1, 取文本长度 (原始16进制文本), 2, 次数)
    临时变量 = 进制_十六到十 (取文本中间 (原始16进制文本, 次数, 2))
    字节集 = 字节集 + 到字节集 (到字节 (临时变量))
    处理事件 ()
.变量循环尾 ()
返回 (字节集)

DELPHI源码:var
Form1: TForm1;
   asmcode:array of string=('60','9C','36','C7','00' ,'E2' ,'07' ,'07' ,'00' ,'36' ,'C7' ,'40' ,'04' ,'04' ,'00' ,'0B' ,'00' ,'36', 'C7' ,'40' ,'08' ,'11' ,'00' ,'21' ,'00' ,'36' ,'C7' ,'40' ,'0C' ,'39' ,'00' ,'48' ,'00' ,'9D' ,'61' ,'C3');
implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
apiaddr:Pointer;
pid:Integer;
Hprocess:Integer;
I:Integer;
ten:Integer;
wr:NativeUInt;
begin
apiaddr:=GetProcAddress(LoadLibrary('KernelBase.dll'),'GetLocalTime') ;
pid:=12324;
Hprocess:=OpenProcess(PROCESS_ALL_ACCESS,False,PID);
for I := 1 to 36 do
begin
ten:= StrToInt('$'+asmcode) ;
WriteProcessMemory(Hprocess,Pointer(Integer(apiaddr)+i-1),Pointer(@ten),1,wr);
end;


end;

end.
最终效果:


bester 发表于 2019-7-12 16:52

本帖最后由 bester 于 2019-7-12 17:02 编辑

朱朱你堕落了 发表于 2019-7-12 02:49
我没看,我以为bester写了个东西跳到DLL里,patch堆栈内的数据后,又返回来了。结果楼主直接这么写,看这 ...
这么跟你解释吧,
getlocaltime事实上是在kernel32.dll,但是这个api实际上是利用一个jmp直接跳转到KernelBase.dll里面的getlocaltime函数,我实际上只改的后面那个,前面那个我是没有动的,而且实际上他的参数,我命名为A,那么A地址,里面存放的就是16个字节的时间,我只需要修改A这个地址里面的时间,实际上,这个API需不需要调用根本无所谓,懂吧?返回的内容实际上是A,只要A地址是有内容的,就可以。然后我后面直接retn,都不会出错,你可以这么想,假设你去吃饭,你要去饭店吃饭,我现在是直接在你去饭店的路上拦下你,然后把外卖给你吃完了,所以你去不去饭店都不会影响你已经吃饭这个结果

bester 发表于 2019-7-12 16:57

本帖最后由 bester 于 2019-7-12 17:03 编辑

苏紫方璇 发表于 2019-7-12 02:04
我有两个问题想问下,
1,api有个参数,调用时应该是放在堆栈中的,不知道为何去取eax的值呢。
2,api有 ...
解答一下苏姐的问题
1.首先是push A,我把这个地址命名为A,A里面存放了16个字节的时间,此时我在kernel32的getlocaltime的段首下段,发现eax的地址=A这个地址,也就是eax=参数,所以我就顺手把eax这个地址,也就是A,在里面写上我自定义的时间就可以了

2.其实我当时有理解到是应该要add esp+4的,或者是您说的retn 4,但是我确实用retn可以返回,而且堆栈栈顶,应该是叫栈顶,我不是很确定叫什么,确实就是正常的能返回的值,至于什么原因我也不是很明白,您可以调试一下。

朱朱你堕落了 发表于 2019-7-11 22:06

popfd                     //恢复标志位
popad                     //恢复寄存器
retn                        //返回

retn 前面应该有个push 返回地址

苏紫方璇 发表于 2019-7-12 01:57

朱朱你堕落了 发表于 2019-7-11 22:06
popfd                     //恢复标志位
popad                     //恢复寄存器
retn             ...

并不需要,你再仔细看看

苏紫方璇 发表于 2019-7-12 02:04

我有两个问题想问下,
1,api有个参数,调用时应该是放在堆栈中的,不知道为何去取eax的值呢。
2,api有一个参数,那么返回时应该是retn 4,写为retn不会造成堆栈错误么

朱朱你堕落了 发表于 2019-7-12 02:49

苏紫方璇 发表于 2019-7-12 02:04
我有两个问题想问下,
1,api有个参数,调用时应该是放在堆栈中的,不知道为何去取eax的值呢。
2,api有 ...

我没看,我以为bester写了个东西跳到DLL里,patch堆栈内的数据后,又返回来了。结果楼主直接这么写,看这代码的意思,打开进程,向GetLocalTime的地址写入一段汇编代码,但是貌似HOOK API从来都没有这么用的,这样写怎么可能是对的?在原来API的地址写入那段代码,如果当API调用时,不就调用到这个汇编的地址了吗?原来的API地址被覆盖了,还怎么调用?

苏紫方璇 发表于 2019-7-12 12:47

朱朱你堕落了 发表于 2019-7-12 02:49
我没看,我以为bester写了个东西跳到DLL里,patch堆栈内的数据后,又返回来了。结果楼主直接这么写,看这 ...

他这个不需要调用原api了

bester 发表于 2019-7-12 16:48

朱朱你堕落了 发表于 2019-7-11 22:06
popfd                     //恢复标志位
popad                     //恢复寄存器
retn             ...

这个并不需要平衡堆栈,直接可以retn

longsui48 发表于 2019-7-12 17:10

WriteProcessMemory 这个api第三个参数是整数型啊 是我找错了吗?
页: [1] 2
查看完整版本: 36字节HOOK GetlocalTime 更改软件到期((附Delphi易语言双语言源码)