UID 2
精华
积分 7736
威望 点
宅币 个
贡献 次
宅之契约 份
最后登录 1970-1-1
在线时间 小时
本帖最后由 元始天尊 于 2015-2-20 11:03 编辑
把自己机子上的win7升级为win8.1以后:
1.每次重启后,宽带账号无法登陆,错误651.。。。。。结果百度一下发现是微软bug,安装了某个kb???补丁就ok了
2.msvc启动崩溃,吧Msdev.exe改名就可以了,用windbg调了一下,分析出了一些原因,但是为何改名就可以启动还分析不出来
3.chrome图标双击后弹窗“没有注册类”,网上查了一下,改改注册表,没成功,不打算搞了。
以下是我的分析过程:
用windbg载入,执行到崩溃会有异常Access Violation,此时看调用栈,发现诡异的事情:
0:000> k
ChildEBP RetAddr
WARNING: Frame IP not in any known module. Following frames may be wrong.
0018ed3f 03124100 0x1f2702
0018ed43 4e3e3850 0x3124100
0018ed47 00000000 0x4e3e3850
0:000> !address 03124100
Usage: Stack
Base Address: 030b0000
End Address: 031ac000
Region Size: 000fc000
State: 00002000 MEM_RESERVE
Protect: <info not present at the target>
Type: 00020000 MEM_PRIVATE
Allocation Base: 030b0000
Allocation Protect: 00000004 PAGE_READWRITE
More info: ~3k
0:000> !address 4e3e3850
Usage: Free
Base Address: 03302000
End Address: 50000000
Region Size: 4ccfe000
State: 00010000 MEM_FREE
Protect: 00000001 PAGE_NOACCESS
Type: <info not present at the target>
再用lm查看载入模块,发现栈有问题,初步断定是调用栈损坏,现在无法进入到有问题的函数中,因此要另想办法
~*k查看全部线程调用栈:
0:000> ~*k
. 0 Id: 3084.4ce4 Suspend: 1 Teb: 7ffdd000 Unfrozen
ChildEBP RetAddr
WARNING: Frame IP not in any known module. Following frames may be wrong.
0018ed3f 03124100 0x1f2702
0018ed43 4e3e3850 0x3124100
0018ed47 00000000 0x4e3e3850
1 Id: 3084.1640 Suspend: 1 Teb: 7ffda000 Unfrozen
ChildEBP RetAddr
02f6fde4 77420393 ntdll!NtWaitForWorkViaWorkerFactory+0xc
02f6ff88 76b2919f ntdll!TppWorkerThread+0x259
02f6ff94 7745b5af KERNEL32!BaseThreadInitThunk+0xe
02f6ffdc 7745b57a ntdll!__RtlUserThreadStart+0x2f
02f6ffec 00000000 ntdll!_RtlUserThreadStart+0x1b
2 Id: 3084.2d70 Suspend: 1 Teb: 7ffd7000 Unfrozen
ChildEBP RetAddr
0306fde4 77420393 ntdll!NtWaitForWorkViaWorkerFactory+0xc
0306ff88 76b2919f ntdll!TppWorkerThread+0x259
0306ff94 7745b5af KERNEL32!BaseThreadInitThunk+0xe
0306ffdc 7745b57a ntdll!__RtlUserThreadStart+0x2f
0306ffec 00000000 ntdll!_RtlUserThreadStart+0x1b
3 Id: 3084.243c Suspend: 1 Teb: 7fe9f000 Unfrozen
ChildEBP RetAddr
031afb70 76250927 ntdll!NtWaitForMultipleObjects+0xc
031afcf4 771c5fd0 KERNELBASE!WaitForMultipleObjectsEx+0xcc
031afe28 771c603e combase!WaitCoalesced+0x73 [d:\blue_gdr\com\published\comutils\coalescedwait.cxx @ 70]
031afe50 771c6101 combase!CROIDTable::WorkerThreadLoop+0x4b [d:\blue_gdr\com\combase\dcomrem\refcache.cxx @ 1480]
031aff78 771c6257 combase!CRpcThread::WorkerLoop+0x2e [d:\blue_gdr\com\combase\dcomrem\threads.cxx @ 264]
031aff88 76b2919f combase!CRpcThreadCache::RpcWorkerThreadEntry+0x16 [d:\blue_gdr\com\combase\dcomrem\threads.cxx @ 67]
031aff94 7745b5af KERNEL32!BaseThreadInitThunk+0xe
031affdc 7745b57a ntdll!__RtlUserThreadStart+0x2f
031affec 00000000 ntdll!_RtlUserThreadStart+0x1b
4 Id: 3084.2ae0 Suspend: 1 Teb: 7fe9c000 Unfrozen
ChildEBP RetAddr
032efd00 76250927 ntdll!NtWaitForMultipleObjects+0xc
032efe84 76b29188 KERNELBASE!WaitForMultipleObjectsEx+0xcc
*** ERROR: Symbol file could not be found. Defaulted to export symbols for D:\VS1999\COMMON\MSDEV98\BIN\devshl.dll -
032efea0 50031876 KERNEL32!WaitForMultipleObjects+0x19
WARNING: Stack unwind information not available. Following frames may be wrong.
032efecc 500317e5 devshl!Ordinal5687+0x8a
032efed4 5da272c6 devshl!Ordinal5569+0x24
032eff48 769e0bc4 MFC42!_AfxThreadEntry+0xdd
032eff80 769e0cec msvcrt!_beginthreadex+0xc9
032eff88 76b2919f msvcrt!_endthreadex+0x8a
032eff94 7745b5af KERNEL32!BaseThreadInitThunk+0xe
032effdc 7745b57a ntdll!__RtlUserThreadStart+0x2f
032effec 00000000 ntdll!_RtlUserThreadStart+0x1b
发现出问题的线程为0号线程,而作为跳板,线程4比较靠谱,因此第一个断点设置在500317e5的上一条指令处。重新加载程序,在该处下断点,等断下后将前4个线程冻结,只留当前线程
~*f
~4s
~u
之后运行到线程结束,再切换回0号线程,做“执行到返回”操作N次,直到重现异常,如果发生异常,则记住该位置下次执行之前做步入操作,这样一点点缩小bug出现位置的范围,
devedit!InitPackage+0x56:
50822bb8 85c0 test eax,eax
devshl!Ordinal3467+0x9a:
50036fa3 83c410 add esp,10h
devshl!Ordinal3467+0x95:
50036f9e e847a2ffff call devshl!Ordinal4845+0x30 (500311ea)
devshl!Ordinal3467+0x95:
50036f9e e847a2ffff call devshl!Ordinal4845+0x30 (500311ea)
while ( 1 )
{
v4 = sub_500311EA(*(HMODULE *)(dword_500FFDA0 + 4 * v3), (CStringList *)&v25, 0);
if ( !v4 && !*(_DWORD *)(v2 + 644) )
break;
if ( v4 == 1 )
++*(_DWORD *)a2;
++v3;
if ( v3 >= dword_500FFD9C )
goto LABEL_9;
}
500311EA DevShl.dll Ordinal5125
执行到这里,发现第二次调用该函数时出现异常,因此下次重新加载之后先步过一次,第二次再步入,继续定位:
devshl!Ordinal4845+0x82:
5003123c e8e7010000 call devshl!Ordinal4845+0x26e (50031428)
CStringList::Find((CStringList *)&unk_500FEBD0, v27, 0)
MFC42!CStringList::Find+0x18:
62ffb49e e843feffff call MFC42!operator== (62ffb2e6)
62ffb4a3 84c0 test al,al
0:000> u 62ffb2e6
MFC42!operator==:
62ffb2e6 8bff mov edi,edi
62ffb2e8 52 push edx
62ffb2e9 ff31 push dword ptr [ecx]
62ffb2eb ff150c410963 call dword ptr [MFC42!_imp___mbscmp (6309410c)]
62ffb2f1 f7d8 neg eax
62ffb2f3 59 pop ecx
62ffb2f4 1bc0 sbb eax,eax
62ffb2f6 59 pop ecx
0:000> uf 62ffb2e6
MFC42!operator==:
62ffb2e6 8bff mov edi,edi
62ffb2e8 52 push edx
62ffb2e9 ff31 push dword ptr [ecx]
62ffb2eb ff150c410963 call dword ptr [MFC42!_imp___mbscmp (6309410c)]
62ffb2f1 f7d8 neg eax
62ffb2f3 59 pop ecx
62ffb2f4 1bc0 sbb eax,eax
62ffb2f6 59 pop ecx
62ffb2f7 40 inc eax
62ffb2f8 c3 ret
最后定位到了MFC42.dll的_imp__mbscmp函数中,_imp前缀的函数其实是为导入库_declspec(dllimport)产生的,位于在pe导入表中,里面有4字节数据,系统在加载后动态地将函数_mbscmp真正的地址写入该处以实现动态绑定,之后就可以通过call dword ptr[addr]进行调用了。下面来看
0:000> u MFC42!_imp___mbscmp
MFC42!_imp___mbscmp:
6309410c 0000 add byte ptr [eax],al
6309410e 0300 add eax,dword ptr [eax]
MFC42!_imp___mbscmp 的数据为03000000,
0:000> u .
0003000a 83781800 cmp dword ptr [eax+18h],0
0003000e 751a jne 0003002a
00030010 c74010ffffffff mov dword ptr [eax+10h],0FFFFFFFFh
00030017 c74001000000ff mov dword ptr [eax+1],0FF000000h
0003001e 896040 mov dword ptr [eax+40h],esp
00030021 0000 add byte ptr [eax],al
00030023 00ff add bh,bh
00030025 159426b663 adc eax,offset AcGenral!g_pfnStackSwap (63b62694)
0:000> u poi(6309410c)
00030000 64a1180f0000 mov eax,dword ptr fs:[00000F18h]
00030006 0bc0 or eax,eax
00030008 7420 je 0003002a
0003000a 83781800 cmp dword ptr [eax+18h],0
0003000e 751a jne 0003002a
00030010 c74010ffffffff mov dword ptr [eax+10h],0FFFFFFFFh
00030017 c74001000000ff mov dword ptr [eax+1],0FF000000h
0003001e 896040 mov dword ptr [eax+40h],esp
该处的代码没有任何意义,完全不是mbscmp的代码,mbscmp应该是个比较函数的!!!,而_mbscmp 函数真正的地址为:
0:000> u _mbscmp
msvcrt!_mbscmp:
759f5153 8bff mov edi,edi
759f5155 55 push ebp
759f5156 8bec mov ebp,esp
759f5158 6a00 push 0
759f515a ff750c push dword ptr [ebp+0Ch]
759f515d ff7508 push dword ptr [ebp+8]
759f5160 e80a000000 call msvcrt!_mbscmp_l (759f516f)
759f5165 83c40c add esp,0Ch
也就是说在写导入表时产生了错误,但是为什么是30000呢,带着这个疑问,我又继续分析:
由于_imp___mbscmp是mfc42.dll的,因此需要等待该dll加载以后才可以下断点
sxe ld mfc42
ba r4 6309410C
硬件断点共断下3次:
Breakpoint 0 hit
eax=00000000 ebx=00000294 ecx=75965153 edx=75940000 esi=75941a60 edi=6527410c
eip=778a8db9 esp=0018f8a0 ebp=0018fab0 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!LdrpSnapModule+0x37c:
778a8db9 8b8d50feffff mov ecx,dword ptr [ebp-1B0h] ss:002b:0018f900={MFC42!_imp__GetVersion (6527503c)}
0:000> ub
ntdll!LdrpSnapModule+0x35c:
778a8d99 898590feffff mov dword ptr [ebp-170h],eax
778a8d9f 898558feffff mov dword ptr [ebp-1A8h],eax
778a8da5 3bce cmp ecx,esi
778a8da7 7730 ja ntdll!LdrpSnapModule+0x3a6 (778a8dd9)
778a8da9 85c0 test eax,eax
778a8dab 0f88c3370400 js ntdll!LdrpSnapModule+0x43dd7 (778ec574)
778a8db1 8bbd3cfeffff mov edi,dword ptr [ebp-1C4h]
778a8db7 890f mov dword ptr [edi],ecx
查看写入_imp的地址,发现确实是_mbscmp函数的:
0:000> u ecx
msvcrt!_mbscmp:
75965153 8bff mov edi,edi
75965155 55 push ebp
75965156 8bec mov ebp,esp
75965158 6a00 push 0
7596515a ff750c push dword ptr [ebp+0Ch]
7596515d ff7508 push dword ptr [ebp+8]
75965160 e80a000000 call msvcrt!_mbscmp_l (7596516f)
75965165 83c40c add esp,0Ch
Breakpoint 0 hit
eax=ffffffff ebx=00614c90 ecx=6527410c edx=75965153 esi=0062dce0 edi=00000100
eip=73d5402f esp=0018f9dc ebp=0018fa2c iopl=0 nv up ei ng nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000286
apphelp!SepRouterHookImportedApi+0x7f:
73d5402f 8bda mov ebx,edx
0:000> ub
apphelp!SepRouterHookImportedApi+0x6a:
73d5401a 8bcf mov ecx,edi
73d5401c 83e11f and ecx,1Fh
73d5401f c1ef05 shr edi,5
73d54022 83c8ff or eax,0FFFFFFFFh
73d54025 d3e0 shl eax,cl
73d54027 8b4dc8 mov ecx,dword ptr [ebp-38h]
73d5402a 8945d8 mov dword ptr [ebp-28h],eax
73d5402d 8b11 mov edx,dword ptr [ecx]
这一次是从_imp读取地址,此时该地址还是正常的
0:000> u ecx
MFC42!_imp___mbscmp:
6527410c 53 push ebx
6527410d 51 push ecx
6527410e 96 xchg eax,esi
6527410f 75d3 jne MFC42!_imp___vscprintf (652740e4)
65274111 c29475 ret 7594h
Breakpoint 0 hit
eax=00030000 ebx=0018fa54 ecx=d6e90000 edx=00000000 esi=0018fa50 edi=6527410c
eip=73d54af3 esp=0018f98c ebp=0018f9d0 iopl=0 nv up ei ng nz na pe cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000287
apphelp!SepIatPatch+0x40:
73d54af3 c745e401000000 mov dword ptr [ebp-1Ch],1 ss:002b:0018f9b4=00000000
0:000> ub
apphelp!SepIatPatch+0x26:
73d54ad9 3b3b cmp edi,dword ptr [ebx]
73d54adb 0f8248920200 jb apphelp!SepIatPatch+0x29276 (73d7dd29)
73d54ae1 8b4608 mov eax,dword ptr [esi+8]
73d54ae4 0303 add eax,dword ptr [ebx]
73d54ae6 3bf8 cmp edi,eax
73d54ae8 0f833b920200 jae apphelp!SepIatPatch+0x29276 (73d7dd29)
73d54aee 8b4508 mov eax,dword ptr [ebp+8]
73d54af1 8907 mov dword ptr [edi],eax
此时是写入_imp地址,可以看出这一次写入的地址是0x30000
0:000> u eax
00030000 64a1180f0000 mov eax,dword ptr fs:[00000F18h]
00030006 0bc0 or eax,eax
00030008 7420 je 0003002a
0003000a 83781800 cmp dword ptr [eax+18h],0
0003000e 751a jne 0003002a
00030010 c74010ffffffff mov dword ptr [eax+10h],0FFFFFFFFh
00030017 c74001000000ff mov dword ptr [eax+1],0FF000000h
0003001e 896040 mov dword ptr [eax+40h],esp
从上面过程可以看出,2次写入过程,第一次写入的是正常的_mbscmp地址,而第二次对该地址写入则是错误的,
很奇怪,写一次就够了啊,为什么要写多次,可以看出第二次写入是apphelp.dll搞的鬼,SepIatPatch这个函数我没查到,不过从名称上看,
像是hook Iat,而这块代码因某种原因未成功。
0:000> k
ChildEBP RetAddr
0018f9d0 73d54a31 apphelp!SepIatPatch+0x40
0018fa2c 73d53c72 apphelp!SepRouterHookImportedApi+0x1e6
0018fa70 73d53b37 apphelp!SepRouterHookIAT+0x123
0018fa8c 73d53ae9 apphelp!SeRouterHookDll+0x34
0018fa9c 778608b4 apphelp!SE_DllLoaded+0x6c
0018fac8 778a9485 ntdll!LdrpSendPostSnapNotifications+0xe7
0018fad8 778a9ad1 ntdll!LdrpNotifyLoadOfGraph+0x3c
0018fae8 778a8cf1 ntdll!LdrpNotifyLoadOfGraph+0x22
0018fb10 778b2556 ntdll!LdrpPrepareModuleForExecution+0xf0
0018fcb8 778b17ec ntdll!LdrpInitializeProcess+0x14ec
0018fd08 778995a6 ntdll!_LdrpInitialize+0xad
0018fd10 00000000 ntdll!LdrInitializeThunk+0x10
就研究到这里吧,如果哪位高人知道PEB->VDM结构或者msdev改名之后影响了系统什么变数,不妨告知一二
改了名的msdev1.exe就没有加载apphelp.dll。。。。。。。。。。奇怪