L ZZZZZZ RRRRR SSSSS L Z R R S L aaa Z aaa R R u u S L a Z a RRRRR u u SSSSS XX L aaaa Z aaaa R R u u S XXXX L a a Z a a R R u u S XXXXXX LLLLLLL aaaaa ZZZZZZZ aaaaa R R uuuuu SSSSSS XXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX XXXXXX XXXX Adding a small function (Autostart) to Shell32.dll XX Few days ago I was sorting all stuff I ever downloaded to burn it on a CD and somewhere in the mass of files I found a small app: SGLLock. This app protects applications from being started without entering a password. The idea of the program was quite good, although it was *very* poorly coded. So, at first I wanted to code such an app, too, but then I made thoughts about starting the program at the Windows start. After 30 seconds of making thoughts I came to the point that every standard autostart method can easily be bypassed and I need to find an alternative. The first thing I tried to find out was how the applications in the "normal" startup possibilies are started (Startup-Folder, Win.ini, Registry). A breakpoint on "WinExec", "ShellExecuteA" and "CreateProcessA" right after SICE started, revealed that the correct breakpoint was "CreateProcessA" and that the file shell32.dll started the apps. The code that is responsible for that is here: Remark: I deal with the shell32.dll from the German Win95 OEM version 4.00.950 B; Shell32.dll version: 4.00.1111 - Filesize: 830464 Bytes :7FDBE93C 8B45F4 mov eax, dword ptr [ebp-0C] :7FDBE93F 05CC090000 add eax, 000009CC :7FDBE944 50 push eax :7FDBE945 8945E4 mov dword ptr [ebp-1C], eax :7FDBE948 FF75CC push [ebp-34] :7FDBE94B 8B45F4 mov eax, dword ptr [ebp-0C] :7FDBE94E 0508010000 add eax, 00000108 :7FDBE953 50 push eax :7FDBE954 FF75D0 push [ebp-30] :7FDBE957 6810020004 push 04000210 :7FDBE95C 6A00 push 00000000 :7FDBE95E 6A00 push 00000000 :7FDBE960 6A00 push 00000000 :7FDBE962 FF75E0 push [ebp-20] ;; IMPORTANT PARAMETER :7FDBE965 6A00 push 00000000 * Reference To: KERNEL32.CreateProcessA, Ord:0046h | :7FDBE967 FF155C3CE17F Call dword ptr [7FE13C5C] :7FDBE96D 85C0 test eax, eax ;; IS EAX = 0 (PROCESS FAILED) :7FDBE96F 0F84E3000000 je 7FDBEA58 ;; IF SO, THEN JUMO For what exactly the parameters are, please consult your Win32-API reference. Only so far: the parameter "push [ebp-20] points to a address which holds the memory address of the commandline of the process that should be created. This is the only parameter I am going to touch. The code here is more powerful (and important) as I told you, yet. It does not only start the apps at Windows start, but 99,9% of all applications are started through this code snippet. What about the missing 0,1%? I have no idea. I found two apps which are started different: First, the Windows Explorer, if - and only if - you start it with [WINKEY]+[E] and the HexWorkshop if - and only if - you start it with the file-context-menu. The importance of this code and the shell32.dll in general should make you edit the file carefully and - by all means - keep a backup of the original file. Now we should find some free space inside shell32.dll where we can put the code we have to add. I have chosen the memory adresses 7FE16430 for the code and 7FE16480 for the string which holds the filename of the app we want to start. That is 64430 and 64480 in the file. The next step is thinking about the changes: I got the idea to change the value of [ebp-20] before it is pushed, so that it points to the name of the app (in my case "notepad.exe"). After the process is created we put the old value back in [ebp-20] and call the original process that should have been created. To make sure that our app is not restarted everytime a process is created I implemted a check with GetTickCount to make sure we are still at Win startup. Before we can add this code, we have to put a jump somewhere in the code I presented above. I have chosen to overwrite the three "push 0" opcodes with "jmp 7FE16430" (E9C7FA0500). The last byte of the three "push 0" opcodes stays unchanged as I only need 5 bytes for the jump. Now the code at address 7FE16430: 00064430 8B5D E0FF 1530 3BE1 7F3D 0050 0100 7F31 .]...0;..=.P...1 00064440 C745 E080 64E1 7F6A 006A 006A 00FF 75E0 .E..d..j.j.j..u. 00064450 6A00 FF15 5C3C E17F C705 5CE9 DB7F 6A00 j...\<....\...j. 00064460 6A00 C605 60E9 DB7F 6A89 5DE0 E9CB 84FA j...`...j.]..... 00064470 FF58 5858 5858 EBE0 0000 0000 0000 0000 .XXXXX.......... 00064480 6E6F 7465 7061 642E 6578 6500 0000 0000 notepad.exe..... or for better reading as disassembly: :00000000 8B5DE0 mov ebx, dword ptr [ebp-20] ;; SAVE OLD VALUE IN EBX :00000003 FF15303BE17F call dword ptr [7FE13B30] ;; CALL GETTICKCOUNT :00000009 3D00500100 cmp eax, 00015000 ;; COMPARE WITH 15000h ms (=86 seconds) :0000000E 7F31 jg 00000041 ;; IF GREATER, THAN JUMP :00000010 C745E08064E17F mov [ebp-20], 7FE16480 ;; [EBP-20] NOW POINTS TO NOTEPAD.EXE :00000017 6A00 push 00000000 ;; THE PUSHES :00000019 6A00 push 00000000 ;; WE HAVE :0000001B 6A00 push 00000000 ;; OVERWRITTEN :0000001D FF75E0 push [ebp-20] ;; COMMANDLINE OF APP :00000020 6A00 push 00000000 ;; LAST PUSH :00000022 FF155C3CE17F call dword ptr [7FE13C5C] ;; CALL CREATEPROCESSA :00000028 C7055CE9DB7F6A006A00 mov dword ptr [7FDBE95C], 006A006A ;; PATCH FILE BACK :00000032 C60560E9DB7F6A mov byte ptr [7FDBE960], 6A ;; TO ORIGINAL :00000039 895DE0 mov dword ptr [ebp-20], ebx ;; [EBP-20] IS RESTORED :0000003C E9CB84FAFF jmp FFFA850C ;; JUMP BACK :00000041 58 pop eax ;; THESE POPS :00000042 58 pop eax ;; DO NOTHING BUT :00000043 58 pop eax ;; FIX THE STACK :00000044 58 pop eax ;; AND PREVENT CRASHES :00000045 58 pop eax ;; IF NO PROCESS IS CREATED :00000046 EBE0 jmp 00000028 ;; JUMP BACK TO 28 TO PATCH THE FILE Some explanations: 1. You cannot save the old value of EBX with a push, as this would completely mess the stack, because some parameters of CreateProcessA were pushed before this ebx-stuff and some after. The only way would be restoring it right in front of the call, but it works like this and I left it so. 2. If the GetTickCount result is too big, we jump to a row of "pop eax". Why? The reason is, that we already have some values pushed, but don't call CreateProcessA. In order to correct the stack, we have to pop these values again. 3. Why do we jump to the beginning of the "push"es and not somewhere after the original CreateProcessA after we executed this code? There must be a reason why this code was called (a program should have been executed). After we started our prog, we must be sure to start the app whose start we interrupted. 4. Why do we need to make the GetTickCount check, although we patch the file back to its original form? I encountered two situations where the shell32.dll seems to be reloaded: When you start a file with wordpad and when you start a file directly out of WinZip. So, if you try this out your shell32.dll will nicely crash at startup. The reason is the following line: :00000028 C7055CE9DB7F6A006A00 mov dword ptr [7FDBE95C], 006A006A ;; PATCH FILE BACK The reason is, that we want to patch the file in memory (.TEXT section), but the section you want to patch is Read-Only. To change it to write-access, change the flags of the section to write-access. In my case it was offset 19F and the new value is C0. Now everything works fine (at least at my PC). If it doesn't work at your PC, look through everything, again and don't bother to ask me: lazarus_hf@hotmail.com Hm, btw: Is our method more secure than standard methods? I say 100% (until you have SICE at this PC, but when you have SICE every kind of safety leaves ;) Greetings go to: +Sandman, Acid Burn, alpine, Borna Janes, Carpathia, CrazyKnight, DEATH, DEZM, dimwitz, DnNuke, duelist, Eternal Bliss, Fravia+, Iczelion, Jordan, KnowledgeIsPower, Knotty, Lucifer48, MisterE, Neural Noise, noos, Prof.X, R!SC, rubor, Shadow, SiG, tC, The AntiXryst, The Hobgoblin, TORN@DO, viny, Volatility, WaJ, _y and all the guys I forget and I'll add next time. And many thanx (once again) to Neural Noise, the guy that always saves my lame reversing ass =)