找回密码
 注册
搜索
热搜: 回贴

Come On!一起来体验一下TLS CALL的强大吧,TLS,系统底层

2010-1-22 18:41| 发布者: admin| 查看: 106| 评论: 0|原作者: 云天青


Come On!一起来体验一下TLS CALL的强大吧,TLS,系统底层
2008年06月23日 星期一 下午 01:29
研究TlsCallBack,本例子按照xp sp2的环境而写,98下肯定game over, 2000下没有测过,希望大家告知结果,谢谢



程序编译出来没有TLS表,输入表的区段中找了个块空间,硬加了个表进去



设置OD停在系统断点,截入2.exe

可以对RtlImageDirectoryEntryToData下断 (ntdll.dll中的)

找到这里

7C9484E8 50 push eax //一开始ebx是0, 和ebx比较就是和0比较

7C9484E9 6A 09 push 9

7C9484EB 6A 01 push 1

7C9484ED 8B7D 08 mov edi,dword ptr ss:[ebp 8]

7C9484F0 57 push edi

7C9484F1 E8 6083FEFF call ntdll.RtlImageDirectoryEntryToData //返回值EAX = 4020C0, 是TLS表的始址

7C9484F6 33DB xor ebx,ebx

7C9484F8 895D FC mov dword ptr ss:[ebp-4],ebx

7C9484FB 3BC3 cmp eax,ebx //检测TLS始址是否为0, 这里有, 所以不跳

7C9484FD 74 20 je short ntdll.7C94851F

7C9484FF 8B70 0C mov esi,dword ptr ds:[eax C] //[4020C0 0C]叫做TlsCallBack, 我这里值是4020E0

7C948502 8975 E0 mov dword ptr ss:[ebp-20],esi //4020E0保存在变量A

7C948505 3BF3 cmp esi,ebx //显然4020E0 !=0, 所以不跳

7C948507 74 16 je short ntdll.7C94851F

7C948509 381D 21C1997C cmp byte ptr ds:[7C99C121],bl //不知道反正不跳

7C94850F 0F85 2F2F0100 jnz ntdll.7C95B444

7C948515 8B06 mov eax,dword ptr ds:[esi] //取出4020E0中的值, 值是401040,即CallBack入口

7C948517 3BC3 cmp eax,ebx //如果不等于0就跳走,delphi的程序这里都是0

7C948519 0F85 3A2F0100 jnz ntdll.7C95B459 //例子中我硬加了值401040, 所以要跳走

7C94851F 834D FC FF or dword ptr ss:[ebp-4],FFFFFFFF

7C948523 E8 DA68FEFF call ntdll.7C92EE02

7C948528 C2 0800 retn 8





7C95B459 8945 E4 mov dword ptr ss:[ebp-1C],eax //上面因为401040不为0, 所以跳到这里

7C95B45C 83C6 04 add esi,4 // 4020E0 4

7C95B45F 8975 E0 mov dword ptr ss:[ebp-20],esi // 4020E4保存在变量A

7C95B462 381D 21C1997C cmp byte ptr ds:[7C99C121],bl // 不知道和上面一样,上面jnz不跳,这里je跳

7C95B468 74 0F je short ntdll.7C95B479

7C95B46A 50 push eax

7C95B46B 57 push edi

7C95B46C 68 20B5957C push ntdll.7C95B520

7C95B471 E8 7A4FFFFF call ntdll.DbgPrint

7C95B476 83C4 0C add esp,0C

7C95B479 53 push ebx

7C95B47A FF75 0C push dword ptr ss:[ebp C]

7C95B47D 57 push edi

7C95B47E FF75 E4 push dword ptr ss:[ebp-1C]

7C95B481 E8 0D5DFCFF call ntdll.7C921193 // 跟进去, 看下面

7C95B486 ^ E9 8AD0FEFF jmp ntdll.7C948515 // 跳上去检测下一个CallBack是否存在





7C921193 55 push ebp

7C921194 8BEC mov ebp,esp

7C921196 56 push esi

7C921197 57 push edi

7C921198 53 push ebx

7C921199 8BF4 mov esi,esp //保存Stack

7C92119B FF75 14 push dword ptr ss:[ebp 14]

7C92119E FF75 10 push dword ptr ss:[ebp 10]

7C9211A1 FF75 0C push dword ptr ss:[ebp C]

7C9211A4 FF55 08 call dword ptr ss:[ebp 8] // 第一次, Call 进401040

7C9211A7 8BE6 mov esp,esi //取回Stack, 可见TlsCall中不破坏esi, 不异常出来,就能正常继续下一Call

7C9211A9 5B pop ebx

7C9211AA 5F pop edi

7C9211AB 5E pop esi

7C9211AC 5D pop ebp

7C9211AD C2 1000 retn 10







我例子中的的EP是401000,为了说明问题,我把那儿清空了,现在ep前,因为TlsCallBack到了401040



00401040 C705 E4204000 801>mov dword ptr ds:[4020E4],2.00401080 ; 将下一个CallBack的入口写入

0040104A 6A 00 push 0

0040104C 68 20304000 push 2.00403020 ; ASCII "From Tls CallBack 1"

00401051 68 00304000 push 2.00403000 ; ASCII "Tls CallBack 2 Actived"

00401056 6A 00 push 0

00401058 FF15 08204000 call dword ptr ds:[<&USER32.MessageBoxA>] ; USER32.MessageBoxA

0040105E C3 retn





再来看一下Tls表,表始址是4020C0, 0C处是4020E0称为TlsCallBack, 4020E0指向401040, 这个地址会比ep先获得执行权(98不带)

004020C0 00 00 00 00 00 00 00 00 D0 20 40 00 E0 20 40 00 ........?@.?@.

004020D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................

004020E0 40 10 40 00 00 00 00 00 00 00 00 00 00 00 00 00 @ @.............

401040那句话完了以后,变成下面, 我故意动态的将第二个TlsCallBack入口401080写入,因为这样比较好玩

004020C0 00 00 00 00 00 00 00 00 D0 20 40 00 E0 20 40 00 ........?@.?@.

004020D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................

004020E0 40 10 40 00 80 10 40 00 00 00 00 00 00 00 00 00 @ @. @.........



40105E 返回后

7C95B486 ^ E9 8AD0FEFF jmp ntdll.7C948515 // 跳上去检测下一个CallBack是否存在

由于401080存在,因此,就进入了第二个TlsCallBack







00401080 56 push esi // esi是外面保存的Stack值,不要破坏比较好,压栈保存

00401081 8BF4 mov esi,esp

00401083 AD lods dword ptr ds:[esi] // 从Stack向下寻找ep

00401084 3D 00104000 cmp eax,2.401000 // 我例子中的ep是401000

00401089 ^ 75 F8 jnz short 2.00401083 // 不等就跳上去继续找

0040108B 05 C0000000 add eax,0C0 // 找到了,401000 c0 = 4010c0

00401090 8946 FC mov dword ptr ds:[esi-4],eax // 新的ep 4010C0 写回Stack中的地方

00401093 6A 00 push 0

00401095 68 40304000 push 2.00403040 ; ASCII "From Tls CallBack 2"

0040109A 68 60304000 push 2.00403060 ; ASCII "Change EP to 4010C0"

0040109F 6A 00 push 0

004010A1 FF15 08204000 call dword ptr ds:[<&USER32.MessageBoxA>] ; USER32.MessageBoxA

004010A7 5E pop esi // esi出来

004010A8 C3 retn





在TlsCallBack中可以看到在Stack中看到ep的值, 并且这个ep就是有效, 因此可以动态的改掉

这里4010A8 retn 出来后,下一个TlsCallBack的值是0,因此这里TlsCallBack的工作都完成了, 现在的ep是 4010C0







来到ep

004010C0 C705 E0204000 001>mov dword ptr ds:[4020E0],2.00401100 //将第一个TlsCallBack的入口改掉,以后还会去

004010CA C705 E4204000 000>mov dword ptr ds:[4020E4],0 //第二个TlsCallBack入口清0, 不需要用了

004010D4 6A 00 push 0

004010D6 68 80304000 push 2.00403080 ; ASCII "From new EP"

004010DB 68 90304000 push 2.00403090 ; ASCII "Change Tls CallBack 1 and ExitProcess"

004010E0 6A 00 push 0

004010E2 FF15 08204000 call dword ptr ds:[<&USER32.MessageBoxA>] ; USER32.MessageBoxA

004010E8 6A 00 push 0

004010EA FF15 00204000 call dword ptr ds:[<&KERNEL32.ExitProcess>] ; kernel32.ExitProcess



Call了ExitProcess并没有完,跟进看看就知道了

进去后第一个CallF7,看到下面

7C81CA2B 8B35 FC13807C mov esi,dword ptr ds:[<&ntdll.NtTerminateProcess>] ; ntdll.ZwTerminateProcess

7C81CA31 FFD6 call esi

7C81CA33 8985 20FFFFFF mov dword ptr ss:[ebp-E0],eax

7C81CA39 E8 82000000 call //这个要F7



一路F8到 到 jmp short 7C943EBC,这里一大段是call 进所有的dll DllMain带Detach

从 je 7C943F6B 这句话出来, 再F8十几行到 call 7C9484D9, 这个进去就是最上面的处理TlsCallBack那大段了







因此ExitProcess函数仍会跳进TlsCallBack, 现在第1个TlsCallBack的入口是401100

00401100 68 00002000 push 200000 //如果这里是0,MessageBox会弹不出来

00401105 68 C0304000 push 2.004030C0 ; ASCII "From Tls Call Back 1"

0040110A 68 E0304000 push 2.004030E0 ; ASCII "App had Called ExitProcess"

0040110F 6A 00 push 0

00401111 FF15 08204000 call dword ptr ds:[<&USER32.MessageBoxA>] ; USER32.MessageBoxA

00401117 C3 retn





关于最后一个MessageBox, 我猜由于是已调用NtTerminateProcess所以flag是0的话弹不出来,好在可以用 MB_SERVICE_NOTIFICATION





这个完了以后, 才算真正的完了, 若干F8跑出LdrShutdownProcess,再下面一个Call就是 sysenter


最新评论

QQ|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏ICP备08020429号 )

GMT+8, 2024-9-30 01:32 , Processed in 0.275923 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

返回顶部