大家对这个win32 API一定很熟悉了,那就来看下他的实现:
0:001> x *!GetLastError //搜索符号地址
7c830759 kernel32!GetLastError = <no type information>
0:001> uf 7c830759
kernel32!GetLastError:
7c830759 64a118000000 mov eax,dword ptr fs:[00000018h]
7c83075f 8b4034 mov eax,dword ptr [eax+34h]
7c830762 c3 ret
先获得线程teb,然后从teb+0x34处获得DWORD值,这个值就是错误值。顺带看下线程TEB结构:
0:001> dt _teb @$teb
ntdll!_TEB
+0x030 ProcessEnvironmentBlock : 0x7ffdd000 _PEB
+0x034 LastErrorValue : 0xcb
执行GetLastError验证一下结果是不是为0xcb:
0:000> g
GetLastError:203
写到这,想到teb+0x34是个内存值,调试时修改这个值应该也会影响GetLastError的返回值吧。思路是这样:单步进入GetLastError,当获得teb的值以后修改teb+0x34处的值,最后GetLastError的值由eax返回,试一下:
0:000> l-t //逐指令运行
Source options are 0:
None
0:000> t //准备获得teb的地址
ntdll!RtlGetLastWin32Error:
7c92fe01 64a118000000 mov eax,dword ptr fs:[00000018h] fs:003b:00000018=7ffdd000
0:000> t //
ntdll!RtlGetLastWin32Error+0x6:
7c92fe07 8b4034 mov eax,dword ptr [eax+34h] ds:0023:7ffdd034=000000cb
0:000> r eax //获得teb地址
eax=7ffdd000
0:000> e 7ffdd000+0x34 ff //修改LastErrorValue
0:000> t
eax=000000ff ebx=00000000 ecx=00000001 edx=00000000 esi=00000001 edi=01003678
eip=7c92fe0a esp=0006ff50 ebp=0006ff7c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!RtlGetLastWin32Error+0x9:
7c92fe0a c3 ret
0:000> r eax //GetLastError的返回值
eax=000000ff
最后看下OutputDebugString(buff);的输出:0xFF(Hex)=255
0:000> g
GetLastError:255