In computer programming, DLL injection is a technique used to run code within the address space of another process by forcing it to load a dynamic-link library.[1] DLL injection is often used by third-party developers to influence the behavior of a program in a way its authors did not anticipate or intend.[1][2][3] For example, the injected code could trap system function calls,[4][5] or read the contents of password textboxes, which cannot be done the usual way.[6]
Approaches on Microsoft Windows
There are at least four ways to force a program to load a DLL on Microsoft Windows:
DLLs listed under the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs will be loaded into every process that links to User32.dll as that DLL attaches itself to the process.[7][8][9][5]
Process manipulation functions such as CreateRemoteThread can be used to inject a DLL into a program after it has started.[10][11][12][13][6][5]
A handle to the target process is obtained, this can be done by spawning the process[14][15] or by keying off something created by that process that is known to exist – for instance, a window with a predictable title,[16] or by obtaining a list of running processes[17] and scanning for the target executable's filename.[18]
Some memory is allocated in the target process,[19] and the name of the DLL to be injected is written to it.[20][10]
This step can be skipped if a suitable DLL name is already available in the target process. For example, if a process links to ‘User32.dll’, ‘GDI32.dll’, ‘Kernel32.dll’ or any other library whose name ends in ‘32.dll’, it would be possible to load a library named ‘32.dll’. This technique has in the past been demonstrated to be effective against a method of guarding processes against DLL injection.[21]
A new thread is created in the target process,[22] with the thread's start address set to be the address of LoadLibrary and the argument set to the address of the string just uploaded into the target.[23][10]
Instead of writing the name of a DLL to load to the target and starting the new thread at LoadLibrary, one can of course also write the code to be executed itself to the target and start the thread at that code.[6]
The operating system will now call DllMain in the injected DLL.[24][10]
Note that without precautions, this approach can be detected by the target process due to the DLL_THREAD_ATTACH notifications sent to every loaded module as a thread starts.[24]
Use the debugging functions to pause all threads, and then hijack an existing thread in the application to execute injected code, that in turn could load a DLL.[28][29][4]
On Unix-like operating systems with the dynamic linker based on ld.so (on BSD) and ld-linux.so on (Linux), arbitrary libraries can be linked to a new process by giving the library's pathname in the LD PRELOAD environment variable, that can be set globally or individually for a single process.[30]
For example, this command launches the command "prog --help" with the shared library from file "test.so" linked into it at the launchtime:
LD_PRELOAD="./test.so" prog --help
Such a library can be created with GCC by compiling the source file containing the new globals to be linked, with the -fpic or -fPIC option,[31] and linking with the -shared option.[32] The library has access to external symbols declared in the program like any other library.
The source files depend a lot on function pointers. Overview is recommended.
DLL Injection is similar to 'Injecting' code into an already running process. Many things have been taken from Matt Pietrek's book 'Secrets of Windows 95'.
Function interception means 'intercepting' an API function that was loaded by a statically linked DLL by modifying the address of the beginning of the function's code, resulting in the application to call your 'intercepting' function instead of the original 'intercepted' function. This is similar to the idea in "APIHijack - A Library for easy DLL function hooking" article posted by Wade Brainerd.
DLL Injection
"DLL Injection" is not an accurate name for what my content will actually be. My code will 'inject' a series of assembled assembly language instructions [Code] into some available space in the running process and alters the registers to point at the offset of the 'injected' [code]. The process will of course execute the instructions which will load a certain DLL, which is the DLL that is being injected. Note that this code 'Injects' [code]. The code can be anything, it doesn't necessarily have to load a DLL. Hence, the inaccurate title.
There are two ways to 'Inject' a series of bytes into an already running process. VirtualAllocEx() - which isn't supported in Win9x/ME - will allow a process to reserve or commit a region of memory within the virtual address space of a separate specified process. Use WriteProcessMemory() to write the data in the reserved/committed area of the target process' memory. The other way is to directly use ReadProcessMemory() and WriteProcessMemory() - which is supported in all versions of Windows - to search for some accessible area of the target process' memory and replace the bytes within the area size equal to the size of the code. Of course, you will be saving a backup of the replaced bytes in order to put them all back later on.
(Of course, you can use CreateRemoteThread() instead of all this, but it's not supported in all versions of Windows.)
One good yet slow method of injecting the code is using Windows' debugging functions. Suspend the threads of the running process (using the debugging functions) and use GetThreadContext() and SetThreadContext() to save a backup of all the registers and then modify the EIP register, which is the register that contains the offset of the current to-be-executed code, to point it to the 'Injected' code. The injected code block will have a breakpoint set at the end of it (Interrupt 3h -int 3h-). Again, use the debugging functions to resume the threads, which will then continue executing till the first breakpoint is reached. Once your application receives the notification, all you have to do is restore the modified bytes and/or un-allocate any allocated space in memory, and finally restore the registers (SetThreadContext()). That's all there is to it. The application has no idea of what has happened! The code was executed, and probably loaded a DLL. As you know, loaded DLLs are in an application's address space, therefore, the DLLs can access all memory and control the whole application. Very interesting.
Lookup the MSDN library for more information (MSDN).
Useful points to lookup:
Memory management...you need to know how Windows manages its memory.
How DLLs tick - MSDN - I suggest you read it. Might help in inspirations. Revising isn't bad.
PE/COFF Headers specifications... The most important thing if you're doing this in Win9x/ME - MSDN.
Basic debugging APIs...those are some APIs that allow you to debug certain applications. Lookup the section "Debugging and Error Handling" in MSDN.
Enough knowledge of ASM is required of course...and OPCODES of instructions.
Have a look at the accompanied files: Injector_src.zip.
---
Google Groups - A Message board thread on CreateRemoteThread()'s method.
Function Interception
Notice the DLL project in the zip file. This function is in HookApi.h.
// Macro for adding pointers/DWORDs together without C arithmetic interfering
// -- Taken from Matt Pietrek's book
// Thought it'd be great to use..
#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr)+(DWORD)(addValue))
//This code is very similar to Matt Pietrek's, except that it is written
//according to my understanding...
//And Matt Pietrek's also handles Win32s
//--(Because they it has some sort of a problem)
PROC WINAPI HookImportedFunction(HMODULE hModule,
//Module to intercept calls from
PSTR FunctionModule, //The dll file that contains the function you want to
//hook(ex: "USER32.dll")
PSTR FunctionName, //The function that you want to hook
//(ex: "MessageBoxA")
PROC pfnNewProc) //New function, this gets called instead
{
PROC pfnOriginalProc; //The intercepted function's original location
IMAGE_DOS_HEADER *pDosHeader;
IMAGE_NT_HEADERS *pNTHeader;
IMAGE_IMPORT_DESCRIPTOR *pImportDesc;
IMAGE_THUNK_DATA *pThunk;
// Verify that a valid pfn was passed
if ( IsBadCodePtr(pfnNewProc) ) return0;
pfnOriginalProc = GetProcAddress(GetModuleHandle(FunctionModule),
FunctionName);
if(!pfnOriginalProc) return0;
pDosHeader = (PIMAGE_DOS_HEADER)hModule;
//kindly read the ImgHelp function reference
//in the Image Help Library section in MSDN
//hModule is the Process's Base address (GetModuleHandle(0))
//even if called in the dll, it still gets the hModule of the calling process
//---That's you should save the hInstance of the DLL as a global variable,
//in DllMain(), because it's the only way to get it(I think)
// Tests to make sure we're looking at a module image (the 'MZ' header)
if ( IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)) )
return0;
if ( pDosHeader->e_magic != IMAGE_DOS_SIGNATURE )
//Image_DOS_SIGNATURE is a WORD (2bytes, 'M', 'Z' 's values)
return0;
// The MZ header has a pointer to the PE header
pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDosHeader, pDosHeader->e_lfanew);
//it's like doing pDosHeader + pDosHeader->e_lfanew
// e_lfanew contains a RVA to the 'PE\0\0' Header...An rva means, offset,
// relative to the BaseAddress of module
// -pDosHeader is the base address..and e_lfanew is the RVA,
// so summing them, will give you the Virtual Address..
// More tests to make sure we're looking at a "PE" image
if ( IsBadReadPtr(pNTHeader, sizeof(IMAGE_NT_HEADERS)) )
return0;
if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE )
//IMAGE_NT_SIGNATURE is a DWORD (4bytes, 'P', 'E', '\0', '\0' 's values)
return0;
// We now have a valid pointer to the module's PE header.
// Now get a pointer to its imports section
pImportDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR,
pDosHeader, //IMAGE_IMPORT_DESCRIPTOR *pImportDesc;
pNTHeader->OptionalHeader.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
//What i just did was get the imports section by getting the RVA of it
//(like i did above), then adding the base addr to it.
//// pNTHeader->OptionalHeader.DataDirectory
/// [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
//// IMAGE_DIRECTORY_ENTRY_IMPORT==1 -- Look at that PE documentation.
//// Pietrek's articles in MSJ and MSDN Magazine will be real helpful!
//Go out if imports table doesn't exist
if ( pImportDesc == (PIMAGE_IMPORT_DESCRIPTOR)pNTHeader )
return0; //pImportDesc will ==pNTHeader.
//if the RVA==0, cause pNTHeader+0==pNTHeader -> stored in pImportDesc
//Therefore, pImportDesc==pNTHeader
// Iterate through the array of imported module descriptors, looking
// for the module whose name matches the FunctionModule parameter
while ( pImportDesc->Name ) //Name is a DWORD (RVA, to a DLL name)
{
PSTR pszModName = MakePtr(PSTR, pDosHeader, pImportDesc->Name);
if ( stricmp(pszModName, FunctionModule) == 0 )
//str"i"cmp,,, suggest you to ignore cases when comparing,
break; //or strcmpi() in some compilers
// Get a pointer to the found module's import address table (IAT)
// =====IMAGE_THUNK_DATA *pThunk;
pThunk = MakePtr(PIMAGE_THUNK_DATA, pDosHeader, pImportDesc->FirstThunk);
//This is what i was talkin about earlier...
//In pThunk, if it was image loaded in memory, you'll get the address to
//entry point of functions
//but in a disk file, It's a function name
// Look through the table of import addresses, of the found
// DLL, looking for the function's entry point that matches
// the address we got back from GetProcAddress above.
while ( pThunk->u1.Function )
{
if ( (DWORD)pThunk->u1.Function == (DWORD)pfnOriginalProc )
{
// We found it! Overwrite the original address with the
// address of the interception function. Return the original
// address to the caller so that they can chain on to it.
pThunk->u1.Function = (PDWORD)pfnNewProc;
// pfnNewProc is in the parameters of the function
//pfnOriginalProc = (PROC)(DWORD)pdw1;
return pfnOriginalProc;
}
pThunk++; // Advance to next imported function address
}
They are the functions to write to the LOG file. What the whole project does is inject a DLL into an already running process (mIRC.exe - mIRC chatting program (mIRC)) [in my case]. It then creates a Log file of all the intercepted Winsock functions. Have a look at Successlog.txt. It is highly recommended that you apply the program on mIRC only, since it has been created for it. Have fun coding your own :)
API라함은 특정기능을 수행하는 함수를 뜻합니다. 예를들어 CreateWindow는
윈도우를 생성시켜주죠. 그런데 이러한 API들은 어디에 있는 걸까요? 바로 DLL안에
있습니다. 무슨 말인지 모르시겠다면 지금 당장c:\windows\system32 라는 디렉토리를
열어보세요. 무수히 많은 DLL파일을 볼 수 있을겁니다. 그럼 대체 이 DLL은 어떻게
사용하는 걸까요? 바로 프로그램이 실행될 때 동적으로 불러와서 메모리에 맵핑시킨답니다.
로드시킬 때 사용되는 API는 LoadLibrary와 GetModuleHandle이 있습니다.
또한 이 API에 대한 인자로 필요한 것이 EP입니다. 이 EP의 값을 알아내는 것이 GetProcAddress입니다.
그런데 이런 API는 누가 알려주는 걸까요? 바로 문서입니다. 인터넷을 뒤져보면 API레퍼런스가
있을 겁니다. 디버깅시 궁금한 API가 분명 있을 겁니다. 그럴 때 이 문서를 참조하세요.
Where are DLLs Mapped?
이런 DLL은 어디에 위치하게 될까요? 저번 메모리 강좌에서 마지막에 보여드린
DLL 색션이 생각나시나요? DLL은 거기에 위치합니다. 따라서 여러분은 앞으로 디버깅시
B0000000~BFFFFFFF 사이에 있으면 '난 지금 DLL안에 있구나'라고 생각하시면 됩니다.
추후에 기회가 되면 이 공유메모리 영역을 가지고 재밌는 작업을 해보도록 하죠.
그전에 내공을 부지런히 쌓으셔야 합니다.
3-Major DLLs
윈도를 이루고 있는 핵심 DLL이 3개 있습니다. 그것은 kernel32.dll, GDI32.dll,
user32.dll입니다. kernel32는 시스템과 관련된 작업, GDI는 그래픽, user32는
유저 인터페이스를 다룹니다. 그런데 이 DLL안에 어떠한 것이 있는지 확인할 방법이
없을까요? dumpbin이라는 유틸을 이용하시면 됩니다. 유용한 유틸이니 구해서 쓰세요.
비슷한 기능이 W32dasm에도 있습니다.
Ansi VS Wide
W32dasm으로 메모장을 디스어셈블한 후 import function이라 적힌 곳을
가보세요. 3~40개의 API들이 나옵니다. 바로 메모장은 이러한 API들이 모여서 만들어진
프로그램이죠. 어디 어떤 DLL들이 임포트되었나 보죠. 제것에는
SHELL32.dll
KERNEL32.dll
USER32.dll
GDI32.dll
comdlg32.dll
ADVAPI32.dll
이란 것들이
나오는 군요. 그럼 API는 어떤가요? API는 DLL안에 들어 있습니다. Kernel32.dll
은 어떤 API를 가지고 있는지 볼까요?
Addr:BFFA0AB3
hint(02D5) Name: _lwrite
Addr:BFFA1CD1
hint(005F) Name: DeleteFileA
Addr:BFF9B7BF
hint(02D0) Name: _lclose
Addr:BFF7753A
hint(02D3) Name: _lopen
Addr:BFFA0CDA
hint(01C0) Name: LocalUnlock
....
....
....
Addr:BFF76E9B
hint(017E) Name: GlobalUnlock
Addr:BFF77564
hint(02D4) Name: _lread
Addr:BFF76E57
hint(0178) Name: GlobalLock
이러한 API들이 사용되었군요. 그럼 각각의 API가 어떤 용도로 쓰이는지
알아봅시다. DeleteFileA라는 것을 API레퍼런스에서 찾아보죠. 에구 그런데 DeleteFile
은 있는데 DeleteFileA란 것은 없지요?
여기서 뒤에붙은 A는 Ansi의 약자입니다. 영어권에서 쓰는 것으로 한음절이
한 바이트가 되도록 한거죠. 그런데 이렇게 하면 우리나라말처럼 한음절이 두바이트가
되는 나라는 어떻하나요? 그래서 탄생한 것이 Unicode입니다. 이럴 경우엔 뒤에 W가
붙습니다
The main purpose of a Dynamic Link
Library, or "DLL" as they are more commonly known as, is to provide modular
and/or portable functionality. Simply put, DLLs have three
purposes:
- Package
Up Misc Files
- Provide
Portable Routines
- Provide Packaged Functionality
Package Up Misc Files:
Many developers choose to use DLL
files as resource files to package up such files as ICONs, BITMAPs, WAVE files,
MIDI files, or other MISC files for use by their main application. Doing so
reduces the size of the main program because it doesn't have to store these
files within the EXE file. It also "hides" the files from the user so that you
don't have to flood the program's installation directory with 50 sound files,
giving the user direct access to change, move, or delete them. Putting them in
a compiled DLL restricts their use to those who know how to use them
(programmers).
I'll discuss this topic more in
Lesson 4 "Creating .RES's" (which are resource
files).
Provide Portable
Routines:
The second kind of
DLL is a DLL that is built as generic as is possible. The reason for this is
that by being generic, multiple applications can make use of the same DLL at the
same time - thus saving them the trouble of re-writing code that is already
available.
For example, if I
wanted to make a program that played sounds while it was running (like a game),
I could do one of two things:
1) Dig DEEP
into the MSDN documentation and find out how Windows interfaces with the
computer's hardware and hardware drivers, and figure out how to use complex API
calls to make the computer's sound card make sounds and play sound
files,
- or
-
2) I could simply
call a couple of simple, pre-built functions within the WINMM.DLL (a very popular multimedia DLL that comes with
Windows) or the DX7VB.DLL (a DLL developed to wrap the functionality of DirectX
so it's easy to use with VB). These DLLs
already have sound playback functionality built into them... and they'd probably
do a lot better job of it than I would starting from scratch because they've
been around for many years and have been improved, and revised over and over
until they are stable and powerful.
Obviously choice
number 2 is the wiser choice because it would most likely work better and would
save you hours, even DAYS of researching to "re-invent the
wheel".
DLL's like these are
designed to be used simultaneously by multiple programs at the same time. "HOW
DOES IT DO THAT" you ask? Simple... each time an application makes a call to a
DLL, a copy of that DLL is loaded into memory to be used by that application.
When that application is finished with it or is shut down, the copy of the DLL
that was sitting in memory is unloaded. Multiple copies of the DLL can be
running at the same time and they won't interfere with each other. I'll explain
more about this in a second.
Provide Packaged
Functionality:
The third type of
DLL is one that is NOT meant to be used by multiple programs, but rather is
meant to be used only by one application. What I mean is, if you wanted to
create a program that had several different things going at once, or wanted to
break out different pieces of your program to be handled separately, you could
do so by taking that functionality and putting it into a DLL, and calling the
DLL to do the work away from your main application. This way, you could have
your main application doing task A, while you have a couple
of DLLs working on tasks B, C, & D for you. This is called
multi-tasking and is possible by the use of DLLs, or by the use of
Multi-threading within your application (which is a nightmare to deal
with).
One REALLY good
example of this is a DLL that is used extensively by vbAccelerator.com.
vbAccelerator.com does a lot of "Sub-classing" (which is when you take over some of the functionality that is
normally handled by Windows - like the drawing of a window onto the screen so
the user can see it, or drawing menus when a user clicks on an application's
menu system). Sub-classing can be a very
powerful, yet very dangerous thing because if you don't handle the Windows
events just right, you will cause Windows exceptions and memory access
violations (A.K.A. - THE BLUE SCREEN
OF DEATH). One other big problem
with sub-classing within Visual Basic is that when you call a sub-classing
routine within your code and then try to debug it within the Visual Basic
Integrated Development Environment (VB IDE), you CAN NOT do it correctly! VB
doesn't handle sub-classing well within it's debugging environment and that
makes it impossible some times to properly step through code and edit code in
debug mode.
To avoid these
problems, vbAccelerator has come up with a DLL that handles the sub-classing for
you called "SSubTmer.dll". If you ever download any of the controls or code on
that site, you'll most likely have to download and install this DLL as well,
because it handles the sub-classing. This way, the problematic piece of an
application is pawned off to a DLL to handle off on it's own, while the main
program happily goes about it's business doing more important
things.
Like I said earlier,
when a DLL is called by an application, that DLL is loaded into memory to be
used by that application. To more specific... the called DLL is loaded into the
calling application's memory space. This way, it alone has the ability to call
that copy of the DLL. Therefore, you don't run into problems with multiple
applications calling the same DLL at the same time and causing access
problems.
There are two types
or styles of DLLs that are most often used by programmers. They
are:
- Win32
API / C / C++ Style DLLs
- ActiveX / COM / VB Style DLLs
Win32 API / C / C++ Style DLLs:
The way that this
style of DLL works is functions are declared within the DLL as being "EXPORTED",
which means that they can be called from without the DLL itself. The way
this is done is when you declare the function within the DLL, you include
special key words that the compiler understands and interprets to mean that that
function should be made available to external
programs.
All Windows API
calls are done this way. The majority of the API calls made to Windows are
stored within the KERNEL32.DLL, USER32.DLL, or GDI32.DLL files. In order to
make a call to a function within one of these DLLs from Visual Basic, you have
to declare to VB what function you're calling, where the function is located,
and what parameters (along with parameter data types) are to be passed back and
forth - like this:
' Sets the
last error number
Declare Sub SC_SetLastErr Lib "SUBCLS.DLL"
Alias "_SetLastErr@4" (ByVal iErrNum As Long)
The "Declare" key word
tells VB that this line of code is going to tell it where the named routine is
and how to use it. The "Sub" key word indicates that the specified routine has no
return value. On the other hand, if it did you'd replace "Sub" with
"Function". The word that follows "Sub" or "Function" is the name of the routine that is being specified. "Lib" tells VB what DLL to
look in to find the specified routine. This can be a full path statement, or if
the DLL is placed within the Windows search path (like C:\Windows\System) then
it is not necessary to include the full path, just the DLL name. The
"Alias" key word is OPTIONAL and is only used when the
specified routine name is different than the actual name of the routine found
within the C style DLL. In this case, you'll notice that there's an underscore
( _ ) before the function name and a "@4" on the end of the function name. The
underscore is something that the compiler puts there to differentiate between
the actual function name and what's called the "function entry point" within the
C DLL. The "@4" tells VB that you need to pass a buffer that is 4 bytes long to
the function... this is done by passing the parameter "iErrNum" (Long = 4
bytes).
"HOW DO YOU FIND OUT
EXPORTED FUNCTION NAMES" you ask? Simply open the DLL using a little utility
that ships with Visual Studio or the Windows SDK called "Dependency Walker"
(DEPENDS.EXE) (You can download it here or find
out more about it here or here) You'll notice on the top left there's a window
showing the inter-dependencies of the DLL you opened, on the bottom there's a
break down of each dependency of the DLL, and on the right side of the upper
half of the window, there are two windows with columns. The bottom one of the
two will list all the exported functions and their information. You'll notice
that some functions do not have export names, but do have entry points and
ordinal numbers. You can actually access these functions by using their ordinal
number, but that's a little too advanced for this
lesson.
The key word
"ByVal" and "ByRef" ARE EXTREMELY
IMPORTANT and are the cause of more than
85% of the errors caused by DLL calls such as this. "ByVal" means that the
value contained within the parameter (for example - 4) is to be passed to
the function. "ByRef" means that the reference to the value, or the
address of the memory that holds the value 4 is to be passed (for example
842147). When you pass a reference, or a memory address of a value (also known
as a POINTER), it is possible for the function then to take that memory address
and change the value that resides at that address thus allowing the DLL to pass
back values to VB.
Imagine if you meant
to pass the memory address of the parameter "842147" (which I made up by the
way), and instead passed the value "4", Windows would try to access the memory
at the address "4", which is a protected memory space thus causing an access
violation or memory exception (BLUE
SCREEN OF DEATH)!
The one exception to
the rule is when you pass STRING values. Because VB uses the OLE sub-system to
handle strings as what's called BSTR or B-Strings, you ALWAYS pass
string values "ByVal" whether you are passing the value or the
reference to the parameter. Also, because most DLL calls expect a "Null
Terminated String" to be passed, make sure (when applicable) you add a NULL
character to the end of the string being passed like
this:
Private Declare Sub
MyFunction Lib "MyDLL.dll" (ByVal
MyParameter As
String)
Dim
MyString As String
' You can substitute the VB constant vbNullChar for
Chr(0)
MyString = "Hello
World!" & Chr(0)
Call MyFunction(MyString)
When you take a look
inside of the C DLL "SubCls.dll" that is referenced by the VB declaration above,
you'll see that it looks like this:
// Sets the
last error number
__declspec(dllexport) __stdcall void SetLastErr (int iErrNum) {
LastErrorNum
=
iErrNum;
}
The "__declspec" key
word is one of many ways of telling the C compiler that this is a function. The
"dllexport" key word that is passed tells the compiler that this function is to
be exported by the DLL. The "__stdcall" key word is a VERY IMPORTANT key word for
VB programmers because it is what allows VB applications to make use of these
functions. VB can only call exported functions declared with the __stdcall key
word. The __stdcall key word tells the compiler that the called function (or
the DLL in this case) is the one that pops (or cleans up) the arguments (or
parameters) that are passed to the DLL from off of the memory "stack". The
default declaration type, and the main alternative to "__stdcall" is "__cdecl".
With __cdecl, the calling function (or the application in this case) is the one
that cleans up the parameters that are passed to the DLL from off of the memory
stack.
C style DLLs do NOT
have to be registered like ActiveX DLLs do. They just have to be within the
Windows search path, or within the same directory as the application that is
using it.
You probably won't
be dealing too much with C style DLLs beyond standard calls to the Win32 API
(all Win32 API calls are written in C
using the __stdcall calling convention),
so this section will probably be more applicable, and therefore more interesting
to you.
ActiveX DLLs have
advantages and disadvantages over C style DLLs. An advantage is you don't have
to create a declare statement for every function call, you just set a reference
to the DLL and declare a variable to represent the DLL interface you're
interested in... and away you go! On top of that, when you reference an ActiveX
DLL like that, you get the bonus of "IntelliSense" within the VB IDE - which
means that when you type the name of a variable that you've declared as an
interface of the DLL you just referenced, a drop-down list will appear with all
the properties and methods of that interface, making it easy to use. I'll
explain more on this later.
The disadvantage of
ActiveX DLLs over C style DLLs is you have to register them using REGSVR32.EXE
like this:
This registers the
DLL:
C:\WINDOWS\SYSTEM\REGSVR32.EXE
MyDLL.dll
This unregisters the
DLL:
C:\WINDOWS\SYSTEM\REGSVR32.EXE /U
MyDLL.dll
However, by
registering ActiveX DLLs this way, they can be ANYWHERE on your computer - your
are not limited to the Windows search path. The reason for this is the
REGSVR32.EXE program puts information in your registry that tells Windows
exactly where to find the DLL so it doesn't have to search for
it.
When using Visual
Basic to create DLLs, you don't have a choice of what kind of DLL you want to
create - you can only create ActiveX DLLs. However, you can get software like
BCX (BASIC to
C Translator) that can take your code
and translate it from VB code (well...
BASIC, but BASIC is very close to VB, minus the VB objects) and changes it into C. Once your code has been
translated to C code, you can use a free C compiler like LCC-Win32 to compile it
into a C style DLL. I did this to create the SubCls.DLL that is posted on this
site under the "DOWNLOADS - DLL Files" section.
ActiveX DLLs are
VERY versatile and are designed to be used within any COM-aware application, and
within such environments as ASP, VBScript, C++, etc. This means that you can
use your ActiveX DLL within MS Word, MS Excel, MS PowerPoint, MS Access,
AutoCAD, or any other application that has a VBA interface. You can use your
ActiveX DLL as a server-side object on an IIS server so that you can use it via
ASP or server-side VBScript, etc. You can even use ActiveX DLLs in a C++
project (however, C++ uses ActiveX DLLs in a slightly different way than VB
based environments.
One last note about
ActiveX... OLE is the same as COM is the same as ActiveX. They are 3 terms for
the same technology. Here's a quote from my favorite tech author Dan
Appleman:
"OLE, short for Object Linking and
Embedding is the old name for ActiveX, a marketing buzzword invented in the days
when Microsoft was more afraid of Netscape than of the Department of Justice.
Nowadays, you are more likely to hear the term COM or COM+ [Component Object
Model] describing those technologies that are part of or implemented by
OLE."
- Dan Appleman : "Dan Appleman's
Win32 API Puzzle Book and Tutorial for Visual Basic
Programmers"
Now that we've discussed the different types
of DLLs, lets get into the details of how to actually program an ActiveX style
DLL from within Visual Basic.
When VB starts up, you'll notice that it
shows the following dialog box by default, which prompts you to pick what type
of program you're going to be writing (this is a screen shot
from Visual Basic 6.0 - Enterprise Edition [SP4] - your screen may differ
slightly in appearance):
Select "ActiveX DLL" and click the "Open"
button. This will start up VB's IDE and start you off with a default class
module named "Class1". You'll notice that there is no default Form provided...
nor should there be. The reason for this is DLLs by nature work behind the
scenes and therefore there is no end user interface. DLLs are tools for
programmers, not interfaces for end users. Of course, if you wanted to you
could have your DLL pop up some kind of interface to gather information from the
user or something where appropriate, but you can't just double-click on a DLL
file and have it run like you can with an EXE file.
So how do you use this DLL? How do you
interface with it? That's where the class
module (which was handed to you by default) comes in. Within this class
module, you create public "Properties", "Methods", and "Events" that you'll
later use from your main application, from ASP, or from where ever you'll be
using this DLL.
Before we start adding Properties, Methods,
and Events to our class module, lets make use of a very handy feature - CLASS
EVENTS! Whenever a class is created, a sub routine is called to allow you to
initialize default property values, or run calculations. This sub routine can
be accessed by clicking on the upper left drop down (object list) and selecting
the "Class" object. This will generate the following code for
you:
Private Sub Class_Initialize()
End Sub
Along the same line, when a class is
destroyed by setting it to equal NOTHING, a sub routine is called to allow you
to free up memory used by the class module, etc. This sub routine can be
accessed by clicking on the upper right drop down (event list) and selecting
"Terminate" from the list of events for the "Class" object. This will generate
the following code for you:
Private Sub
Class_Terminate()
End Sub
Lets go ahead and put a message box in each
event to tell us when the events are fired. Do this by putting the following
code in each event:
MsgBox "Class started/ended", vbOKOnly, " "
Lets start on the DLL elements by adding a
few simple properties. The easy way to do this is to have VB put down a
prototype of a property and then modify that to what you need. Click the
"Tools" menu item and select "Add Procedure..." menu option. This will pop up a
simple dialog that asks you for some information to create the property (or function, or sub, or event) from that looks like
this:
You can use this dialog to create a Sub,
Function, Property, or Event prototype. Simply enter the name of the prototype
to create, select the prototype you want (in this case
PROPERTY), and select the scope (in this case PUBLIC
because we want people using our DLL to see this property), and then
click OK. That will insert the following code into your class
module:
Option
Explicit
Public Property Get
MyProperty() As Variant
End Property
Public Property Let
MyProperty(ByVal vNewValue As
Variant)
End
Property
You'll notice that the default data type is
"Variant". You'll want to change this to whatever data type is appropriate for
your property. In our example here, lets change it to a
"String".
The way this works is you've got one
procedure that handles the user's request to retrieve the property's value "GET"
and one procedure to handle the user's request to change the property's value
"LET" or "SET". The SET statement is used for object variable types such as
PictureBox, Form, StdPicture, or StdFont. The LET statement is used for all
other data types. If you take out the LET statement, it makes this property
READ-ONLY to the developer using your DLL. If you take out the GET statement,
it makes this property WRITE-ONLY to the developer using your
DLL.
Now that we have the routines that are used
to return or set the values of this property, we need something to HOLD the
property value, because the routines themselves do not hold values. We'll do so
by putting the following variable declaration in the "General Declarations"
section at the very top of the class module:
Private p_MyProperty As String
I declare property variables with a "p_"
prefix to denote that they are holding a property value (makes em easier to find too), but you can name it anything
you want. Common naming conventions would dictate that you call it
"strMyProperty" or "p_strMyProperty" instead to show that it's a
string.
MAKE SURE THAT YOU DECLARE THE
VARIABLE AS "Private" ! If you declare it as
PUBLIC, every instance of this class module will share the same value for this
property... which kinda defeats the whole purpose of using the same class module
multiple times. Also, make sure that you declare the variable that holds the
property's value as the same data type as the property it self - in this case
"String".
The next step is to assign the value of the
property with the value of the variable like this:
Option
Explicit
Private p_MyProperty As
String
Public Property Get
MyProperty() As String
MyProperty =
p_MyProperty
End Property
Public Property Let
MyProperty(ByVal strNewValue As
String)
p_MyProperty =
strNewValue
End
Property
You can also use the GET and LET routines to
run calculations and return a calculated value based on the input value. This
is a big advantage to just using a Variable or Type to hold values... you can
run code when the user reads or writes a property
value.
Lets add another property, but this time,
lets pass an additional parameter to it - an Index. You can pass
whatever parameters you want to/from properties, but Index makes sense for
getting or setting array values. We add the following code to our class module
to do this:
Private p_MyNumbers(5) As Long
Public Property Get
MyNumbers(ByVal Index As
Integer) As Long
If Index >= 0 And
Index <= 5 Then
MyNumbers =
p_MyNumbers(Index)
End If
End Property
Public Property Let
MyNumbers(ByVal Index As
Integer, ByVal strNewValue As
Long)
If Index >= 0
And Index <= 5 Then
p_MyNumbers(Index) =
strNewValue
End If
End
Property
Now you know how to use Properties, lets add
a Method! That would be fun, right? "BUT WHAT IS A METHOD" you ask? A "Sub"
or a "Function" routine when within a class module is called a "Method". Simple
enough, right?
Public Function
Get_2_Plus_2() As Integer
Get_2_Plus_2 = 2 +
2
End
Function
Subs and Functions within class modules are
treated just the same as within any other part of your project. However, if you
declare your Sub or Function PRIVATE, you can only
use it within the class module. If you declare it PUBLIC, then you can use it as part of the class object
(because classes really are objects) anywhere in your
project. If you declare it FRIEND (something you can only do within a class module), then
other parts of your project can see it, but once compiled, that method will
appear as if it does not exist. It's a way of allowing access to it for you,
but restricting it for others. The FRIEND declaration can be used for
properties as well as methods.
What have we left out so far? EVENTS!
Events are actions that take place to notify the application of the user's
activities so it can react appropriately. For example, if you have a Label
control placed on a form called "lblURL" that has it's caption set to
"http://www.thevbzone.com" and you want the caption to be UNDERLINED as if it
were an internet link when the user holds their cursor over it. To do this,
you'd use the MouseMove event like this:
Private Sub
lblURL_MouseMove(Button As
Integer, Shift As Integer,
X As Single,
Y As Single)
lblURL.FontUnderline =
True
End Sub
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
lblURL.FontUnderline =
False
End
Sub
To create an event, we open up the "Add
Procedure" dialog again by going to the "Tools" > "Add Procedure..." menu
option and selecting "Event" as the procedure type. Lets add an Event called
"PropertyChanged". When we click OK, the following code is placed in our class
module for us:
Public Event
PropertyChanged()
To activate this event, we use the "RaiseEvent" function along with the name of the event to
fire. Lets make this event fire every time the user changes a property
value... so we put the following code in the "LET" routine of every
property:
RaiseEvent
PropertyChanged
At this point, we have all the main aspects
of a working DLL, we just need to compile it! Lets check it first. To do this,
type "ME." somewhere in your class module. You'll notice that when you press
the <PERIOD> key, an "IntelliSense" pop up will drop down to show you all
of the properties and methods that have been defined. This is what the user
will see when they are using your DLL (minus the elements that are declared
PRIVATE or FRIEND). It will look something like
this:
To me, this is one of the BEST features of VB
because I know I'm not mis-spelling the properties and methods because I can
just select the one I want from the list displayed. I also don't have to
memorize what exactly I called the different elements of the class because I can
just browse the displayed list of elements until I find the one I want. You'll
notice that Functions/Subs/Methods have a little green icon next to them, and
properties have a little hand icon next to them. This helps you to quickly
distinguish which is which when you're coding.
Another way to check up on your routines is
to open the VB Object Browser by selecting the "View" > "Object Browser" menu
option, or by pressing the <F2> key. Select the name of your project from
the very top left drop down box and you'll notice that all the components of
your project are listed in the left window and the elements of each component
are listed in the right window. Select the class module we've been working on
"Class1" and you'll notice that all of our properties, methods, and events are
listed there for us. If you click on one, it will tell you more about
it:
However, at this point none of them have
descriptions. Let's remedy that, shall we?! :
)
Close the Object Browser and go back to our
class "Class1". Select the "Tools" > "Procedure Attributes..." menu option
and the following dialog will show up:
Select which element you want to change from
the "Name" drop down,and change the description to whatever you want the user to
see when he/she views the details of that Property/Method. You can also make
the specified property the DEFAULT property by changing the "Procedure ID" drop
down to "(Default)". What this does, is makes is so that if you set a variable
equal to your DLL's interface and do not specify a property or method, the
default one will be assumed. This is optional, but a good idea. For example,
the "Text" property of TextBox controls is the default so you don't have to
specify MyTextBox.Text, you can just specify MyTextBox and the Text property is assumed. Same with
Label controls, the "Caption" property is the default. You can also set a
method to be the "About Box" for your DLL by setting the Procedure ID to
"AboutBox". This is more applicable to ActiveX Controls than it is to ActiveX
DLLs because setting the Procedure ID of a method of an ActiveX Control allows
you to click on the ActiveX Control at design time with in the VB IDE when it's
placed on a Form, User Document, etc. and then click the "About" button in the
properties window to run that method (which is assumed to show an About
window).
There are several other settings here to
control the behavior of your ActiveX DLL or Control. Play around with them and
find out what they do.
Now that we've setup a description for our
properties and methods, go back to the Object Browser by pressing the <F2>
button and check out the elements of our class module
now:
You'll notice that now there's a little blue
dot next to the "MyProperty" property which tells us that that is the DEFAULT
property for this interface. You'll also notice that now there's a description
in the bottom gray area.
Have you noticed that I've
been using the terms "class module" and "interface" interchangeably throughout
this lesson? I hope that you have because it's an important point. You can
actually have multiple class modules within a DLL, thus giving the developer
multiple uses from the same DLL. Each class module you add represents a user
interface to your DLL because that's all they will be able to see from your
DLL... the class modules, and the class modules' public elements. Form1 shows
up here because we are still developing the DLL, but you'll see a difference
when you go and compile it and try to use it within another
project.
At this point, we're ready to go ahead and
compile our DLL project. Lets go ahead and give our only interface a little
better name. Click on the "Class1" class module in the "Project" window of
VB's IDE and change it's name in the "Properties" window to something like
"MyInterface". Also, lets change the name of the DLL project to something like
"MyDLL" by clicking on "Project1" in the "Project" window and changing it's name
in the "Properties" window.
Next, select the "File" > "Make MyDLL.dll"
menu option. This will pop up a dialog asking you where you want to compile the
DLL to. DON'T COMPILE IT JUST YET! If
you'll remember what I discussed at the end of Lesson 1, you need to set the DLL
file's attributes by clicking on the "Options" button on this dialog. Make sure
to set the appropriate version number, file title, comments, copyright, etc.
under the "Make" tab.
Click the OK button, and then click the next
OK button as well to start compiling your DLL.
WE'RE DONE !! -
PSYCH ! ;P
Now that you have compiled the DLL, you need
to do a few things. First off, when VB compiles an ActiveX DLL like we just
did, it automatically registers it in your Windows Registry. If you open up the
"Windows Registry Editor" by going to the "START" > "Run" menu option of your
system try and type REGEDIT.EXE, you will start up a
very handy tool that we can use to see what's going on in the registry. Go to
the "HKEY_CLASSES_ROOT" section and browse down until
you see "MyDLL.MyInterface". This is the registry
entry for our DLL and the one interface that we defined. Each interface you
create will have it's own registry entry here. You'll notice that under this
registry entry, there's a key named "CLSID" (which stands for Class ID). If you select it you'll
notice that there's a HUGE number set for the value of this key. That is the
number that represents our DLL's interface GUID (which
stands for Graphical User Interface iDentification number) or UUID
(which stands for Universally Unique
IDentification number). This
is a number that is generated by Visual Basic and guaranteed to be unique, and
identifies your DLL's interface. This prevents problems that could pop up if
more than one person created a DLL called "MyDLL" with an interface called
"MyInterface" because the GUID numbers would be
different.
If you go up to the CLSID key of the
HKEY_CLASSES_ROOT section, you'll see a HUGE list of GUIDs / UUIDs. Find the
one that represents our DLL and find the "InprocServer32" sub-key under it.
You'll notice that it tells us where the physical DLL is located
here:
This process that we just went through is
what Windows goes through to find the physical file each time you reference an
ActiveX DLL or Control interface.
If you'd like to move the DLL from it's
current location, you have to do the following:
1) UNREGISTER the DLL by going to a command
prompt and typing the following:
C:\WINDOWS\SYSTEM\REGSVR32.EXE /U C:\MyDLL.dll
This removes all entries in the Windows Registry that refer to our
DLL.
2) Physically move the DLL to wherever you'd
like to to reside (like
C:\WINDOWS\SYSTEM)
3) RE-REGISTER the DLL by going to a command
prompt and typing the following:
C:\WINDOWS\SYSTEM\REGSVR32.EXE
C:\MyDLL.dll
Now we are ready to go ahead and use our DLL
within another application. Lets go ahead and start up a standard EXE project
as described in lesson 1 to test our DLL. Once we've started a new project, we
need to REFERENCE our DLL. To do so, select the
"Project" > "References..." menu option. This will display the References
dialog. Once in this dialog, locate our DLL by clicking the "Browse" button
and physically locating it, or by looking for it in the list of available
references. Once we have references our DLL, to use it we need to create a
variable to represent our DLL interface. To do so, declare a variable like
this:
Private TEST As MyDLL.MyInterface
Once we have created a variable to represent
our interface, we need to initialize it by calling the following
code:
Set TEST = New MyDLL.MyInterface
Once it has been initialized, we can use it.
If you type variable name and press the <PERIOD> key, you'll notice an
IntelliSense pop up similar to the one we saw when developing the DLL. However
when we press the <F2> key as we did before, and select "MyDLL" as the
project, we only see the class module "MyInterface" in the listed classes
section. This is because, as I stated earlier, classes are the only exposed
interfaces to DLLs. When we click on the "MyInterface" class, we see it's
PUBLIC elements listed on the right along with their
descriptions:
You can now call the "Get_2_Plus_2" method
via the TEST variable, or get the values of the properties by specifying them.
However, did we leave out the "PropertyChanged" event? "HOW DO I GAIN ACCESS TO
EVENTS I'VE DECLARED" you ask? You actually have to change the variable declare
statement to tell VB that you are interested in making use of any events
available within this interface. To do so, declare the variable TEST like
this:
Private WithEvents
TEST As MyDLL.MyInterface
The "WithEvents"
key word makes the "TEST" object available to you in the upper left drop down
(object list). Select it from the drop down and VB puts generates the
following code for you:
Private Sub
TEST_PropertyChanged()
End Sub
Because "PropertyChanged" is the only event
declared for this DLL, it's the only one listed in the upper right drop down
(event list). Let's go ahead and put a message box here to tell us when this
event fires. So when we put it all together, it looks like
this:
Option
Explicit
Private WithEvents TEST As MyDLL.MyInterface
Private Sub Form_Load()
Set
TEST = New MyDLL.MyInterface
End Sub
Private Sub Form_Unload(Cancel As
Integer)
Set TEST =
Nothing
End Sub
Private Sub Form_Click()
TEST.MyNumbers(1) = TEST.Get_2_Plus_2
End Sub
Private Sub TEST_PropertyChanged()
MsgBox "A property has changed", vbOKOnly, " "
End
Sub
When you run this program, you'll see a
message box when the program starts telling you that the DLL interface was
initialized. Then when you click on the form, you'll see a message box fired by
the "TEST_PropertyChanged" event that lets you know the property changed in the
"Form_Click" event. Then when you close the form, you'll see one last message
box telling you that the DLL interface was
terminated.
You can also use ActiveX DLLs in Windows Script files by putting the following in a text
file named "TEST.vbs":
On Error Resume
Next
Dim TEST 'As MyDLL.MyInterface
Set TEST =
WScript.CreateObject("MyDLL.MyInterface")
TEST.MyNumbers(1) =
TEST.Get_2_Plus_2
Set TEST =
Nothing
You can also use ActiveX DLLs in ASP/VBScript by registering it on an IIS Web Server and
calling it from a web page like this:
<SCRIPT LANGUAGE="VBScript" RUNAT="SERVER">
On Error Resume Next
Dim TEST 'As
MyDLL.MyInterface
Set TEST =
SERVER.CreateObject("MyDLL.MyInterface")
TEST.MyNumbers(1) =
TEST.Get_2_Plus_2
Set TEST = Nothing
</SCRIPT>
THAT'S IT !! Congratulations, you're now an
expert on DLLs... er... well at least you know enough about them to use them
correctly. =) HAVE FUN !
Manually Unpacking a Morphine-Packed DLL with OllyDbg
Tools Required: OllyDbg, Stud_PE, UltraEdit or any suitable hexeditor Skill Level: Beginner
Unpacking executables in OllyDbg is usually pretty straight-forward, but sometimes, we come across a DLL that is packed, which can affect how we approach the problem. Due to the way OllyDbg uses the loaddll.exe wrapper to analyze DLLs, the DLL's initialization code will run before we hit our startup breakpoint, allowing the code to perform debugger detection or any other nasty tricks before we get a chance to stop it.
This tutorial gives a step-by-step illustrated guide to unpacking a Morphine-packed DLL using OllyDbg. In this case, our target is a piece of malware identified by Kaspersky Anti-Virus as "Trojan-Proxy.Win32.Agent.jz". RDG packer detector tells us that it is packed by Morphine 2.7.
If we load the file as-is, OllyDbg will detect that it is a DLL file, and prompt us to use LOADDLL.EXE to analyze it.
This is not what we want, so we close this out. Before we load this bug into Olly, we are going to make a small change, to make Olly think that our target is a standalone executable instead of a DLL. We do this by using Stud_PE to locate the "Characteristics" field of the PE header. There is a single bit that we want to toggle in the byte at 0x117. We can do this by changing the value 0x21 to 0x01. Save the file, and now we can load it into OllyDbg as if it were an EXE.
Now when we load the file into Olly, we are taken to the ModuleEntryPoint, and can begin our unpacking.
When a morphine-packed DLL runs, it will unpack the original file and then copy it to memory allocated by VirtualAlloc. All we need to do in order to dump the original file is to interrupt this process and dump the memory before it is loaded and executed. We can do this by finding the VirtualAlloc function (use CTRL-G to go to a memory location by address or by exported name) and setting a breakpoint on it.
Some packers may use anti-debugging tricks or check the first few bytes of the imported functions to insure that they do not have software breakpoints set. In this case however, there are no tricks, and we can simply set our breakpoint at the start of the VirtualAlloc subroutine, and run the code by pressing F9.
Once we come to the breakpoint, the original code is unpacked and ready to be copied. We can locate the code in memory by going to the OllyDbg memory map window and right-clicking on the first section after the PE header, and selecting "Dump". This opens a window with our dump in "Disassemble" mode. Right-click on the window and choose "Hex->Hex/ASCII (16 Bytes)" and you'll see the hexdump as shown below.
Scroll through the output and find the PE header, starting with the familiar bytes "MZ" followed by the usual "This program must run under Win32" verbage. If this is present, it means our unpack worked, and we can dump the memory by right-clicking on the dump window and selecting "Backup->Save data to file".
At this point all we need to do with the memory dump is delete the bytes preceding our PE header, and truncate the file at the proper length. I usually use Linux for my low-level file manipulation, but since I know most of you reading this tutorial are working on Windows, I'll show the process using the UltraEdit-32 hex editor.
First, open the memory dump file in UltraEdit and locate the MZ bytes indicating the start of the PE header. Note the offset into the file, in this case, 0x4969 hex, in decimal, 18793.
Go to the start of the file, select the first byte, right-click and choose Edit->Hex Insert/Delete or hit CTRL-D. In the dialog that pops up, choose "Delete" and enter the number of bytes to delete up to the PE header start.
Now all we have to do is truncate the file at the correct location. (It won't hurt anything in terms of functionality if you skip this step; the file will just be larger than it needs to be.) Save the file in UltraEdit, then open the saved file in Stud_PE. Look at the "Sections" tab, and note the RawSize and RawOffset fields of the last section of the file. Add them together, and that tells you the overall raw size of the original file. In this case, 0x25800 + 0x3800, which equals 0x29000.
Go back to UltraEdit, and select the byte at offset 0x29000. Hit CTRL-D to bring up the delete bytes dialog again, and now enter a sufficient number of bytes to truncate the rest of the file.
We now have a copy the original DLL as it was before being packed by Morphine. We can verify its integrity by loading it into Stud_PE and checking that all of the components of the file have sane values and that the import table actually shows imports from various system DLLs, which would not have been shown in its packed state. The export table should now also show any exported functions in the DLL.
Images and Links FIXED! Modifying your shell32.dll
Introduction
Modifying your shell32.dll has become THE way for complete system customisation. What is your shell32.dll? It is the dll that contains most of Window's XP's icons. You could say it is the 'core' of Windows XP's icons. With this tutorial you will learn to modify your shell32.dll. This tutorial was made so that even 'newbies' can follow and understand, and the focus will be on changing icons. Also, if you already do not know, the operating system used here is Windows XP.
We are going to use Resource Hacker to modify your shell32.dll. So you are probably thinking to yourself, I could just do this in a more easy and quick way with a third party program such as Microangelo or Axialis IconWorkshop. But the truth is, most people cannot afford such software, and you learn a lot more this way. Plus this was the way I first customised icons my PC, and still do.
Some benefits of modifying your shell32.dll, using Resource Hacker:
* You do not need to invest in expensive software, in order to change icons on your pc. * This is especially useful becaue, after you have made to changes to a particular dll file, you can save it for future use, so that you will not have to hack that particular dll file again. For example, on my computerI have several different dll files that are 'themed' with certain icon sets, such as MMX Mercury, Mercury, Snow.E 2, Crystal, or G.A.N.T. So when I feel like I want to use Crystal, all I have to do is just replace the current shell32.dll I am using, with my hacked one. Ten minutes later, if I want to use Snow.E 2, all I have to do is replace the Crystal dll with my Snow.E 2 dll.
Some disadvantages:
* The task may be a bit daunting for un-experienced users. * There is ALWAYS a possibility that your pc will not function properly if you carry out this tutorial. Although this is highly unlikely, back up your data before attempting any dll modification. * The process can consume a lot of your time, but the the advantages greatly outweigh this.
So let me say this again: BACKUP YOUR DATA. I, or ntfs.org cannot be held liable to any data loss that might occur. So lets begin.You can click on any of the screenshots in this tutorial to view a larger version.
Part 1 - Getting ready
You will need the following to start:
* Download Resource Hacker. This is an excellent freeware program that lets you view, modify, rename, add, and delete resources from win32 executables and resource files. In simple terms: this the the program you will use to modify your dll files. * You also need an extracting utility like WinRAR. Since most icons come in packs, they are often compressed into formats such as .zip or .rar. * Download some icons. Some good places are deviantart.com, deskmod.org, or visit any other site that you know of. * You may want to get this that I have, so you can view all the icons within the most common dll file that is hacked, the shell32.dll. Use it as a reference as most dll's contain hundreds of icons. * Print this tutorial out, as you might want the instructions for the part where you reboot in Safe-Mode with Command Prompt. * Like I said before, backup your data.
Note: If you have already downloaded your shell32.dll, at this point you can proceed to "Part 3- Save, Replace, Enjoy".
Part 2 - Modify it!
1.) First of all, extract your icons. Go to your My Documents folder, and make a folder called 'My Icons'. Now, extract your icons into that folder. If you are having trouble using winzip, or winrar, look at this screenshot. Your icons are now ready to be used for dll hacking.
2.) Lets get Resource Hacker ready. The file comes in .zip format. If you are having trouble with this, look at this screenshot. After you have extracted resource hacker, double-click on 'ResHacker.exe'. This will start Resource Hacker.
3.) With Resource Hacker open, press Ctrl+O. This will bring up a dialog box. Where it says 'File Name' type in "x:\windows\system32\shell32". Replace the x with the drive name where windows xp is installed on your pc.
Since we are replacing the icons in the shell32.dll, click on the '+' by by the 'Icon Group' folder. Remember, the 'Icon Group' folder, not the 'Icon' folder.
5.) Here is where the list of the icons in the shell32.dll I have comes in. If you did not download the list earlier, you can get it here. First think about what icon you want to replace. Then, using Find in notepad, locate its number. For example, if I wanted to replace the Network Drive icon, then I would go to Edit -> Find... and then I would search for 'Network Drive'.
Now I know that the icon number for Network Drive is 10.
6.) This is when we replace the icon. Click on the 'Open File with new icon...', this will bring up an Open dialogbox. We now want to go to where you extracted those icons. Find an appropriate icon to replace the icon you want to replace.
Click on 'Replace'. Make sure you have the right icon selected though. If you see a little hand instead of the icon you wanted do not worry. Do the same procedure for every icon that you want to replace. The icon in place of the old one might look like a a hand, but don't worry about that.
1.) Go to File -> Save As ..., and save your modified shell32.dll with the name 'shell32_modified.dll', in the following directory: x:\windows\system32\shell32. Replace the x with the drive name where windows xp is installed on your pc.
Because windows is always using the shell32.dll(even as your reading this), you will need to replace your current shell32.dll outside of windows. The easiest way to do this is to:
* Reboot * Press F8 as windows boots up (Right before the windows xp boot screen). * Choose 'Safe Mode with Command Prompt' as your option. * Once you login, type in 'cd..' and then type that in again. * Type in 'cd windows/system32 * Type in 'ren shell32.dll shell32_original.dll' * Then type in 'ren shell32_modified.dl shell32.dll' * Reboot
Now, login to Windows and enjoy your new, modified shell32.dll!
Conclusion
Using this technique, you can replace various AVIs, bitmaps, and cursors too. You can also use this same technique to modify other dlls.
Information Security & US & Life & Love & Fashion & Hacking & Passionhack, web security, game security, game hack, fps, ava, wow, starcraft II, soldier front, gunz, reverse engineering, SQL injection, XSS, hacking, penetration testings, IT, internet technlogoy, security, penetratoin testing, XSS, XSRFCEOinIRVINE