

                     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 =)