You are on page 1of 6

Difficulty: Medium Learn how to create a keygen on-the-fly Creator: m101 Target: Ad Muncher v4.4 URL: http://www.admuncher.

com The first thing to do is to open up Ad Muncher and find out what is going on and how it works. Then load up procdump and dump both the exe and the dll seperately. Look at the size of the exe and the dll, the exe is only a few kbytes, but the dll is much bigger (over a hundred kbytes) and has been packed with UPX. From this we can tell that the dll is the main program and the exe is a loader. Since we are doing this on-the-fly, we wont be needing Win32DASM, but if you do, then you can now disassemble the dumped files ;) Load up Ad Muncher, enter some bogus information. When you choose what bogus information to include, make sure it DOES NOT contain any characters by choice. This is because it will normally pass most checks on input characteristics. Also, if you were smart enough to actually READ the registration page first, you would have noticed this: 'Please enter your name and code below, the code consists of two hexadecimal numbers (ie: numbers 0-9 and letters A-F) joined with a dash.' Your serial you enter should be something like '012345-543210'. Then set a breakpoint with softice on GetWindowTextA, This means when you Click register, softice should popup. You should be in the middle of a GetDlgItemTextA call, so press F12 twice to return to Ad Muncher. If you didnt break, then you arent using Windows 2000 like i am, and you will have to just set a breakpoint on GetDlgItemTextA directly. Back in the Ad Muncher code, you should see something like this:
00751431 00751433 00751436 0075143B 0075143C 6A68 FF7508 E80D0C0000 40 A33C7A4B00 push 00000068 push [ebp+08] Call USER32.GetDlgItemTextA inc eax mov dword ptr [004B7A3C], eax

Disable your breakpoints with 'BD *' and then trace through the

code with F10 till you find anything that looks interesting. By the term 'interesting' i mean any use of tables like 'mov ecx, [eax*4+005B8A1C]' or any loops that contain a 'LODSB' or 'LODSW'. Also you may want to look for stuff like 'xor ecx, ecx ; mov eax, [ecx + 005B8A1C] ; inc ecx'. You should come upto this after a minute of searching:
:loop LODSB ADD ECX, EAX ROR ECX, 08 ADD ECX, EBX CMP AL, 00 JNZ LOOP NOT ECX

Now if you look at the start of this function and checkout esi you will find that it contatains your username and ebx holds '00012345'. Wow, the first half of our serial and our username ;) Ad Muncher takes your serial, splits it in two, then moves the location of your username into esi, and sets the value of the first half of the serial in ebx. Next it takes a character from esi, starts a running total, rolls the register right 8h times, adds the first half of the serial in ebx to the total and then loops until all of the characters have been read. After this is NOT's the total to give the second half of the serial in ecx. To make a keygen all you have to do now is convert the routine into any language you choose and give it a little interface. You can now use Ad Muncher to create valid serials without any troubles at all, but it is better to have a seperate keygen, so have a go at making one, here is the one I created:
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------;Ad Muncher v4.4 Keygen by m101 for Phrozen Crew .386 .model flat,stdcall option casemap:none include \masm32\include\windows.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib

WinMain proto :DWORD,:DWORD,:DWORD,:DWORD .data ClassName db "SimpleWinClass",0 AppName db "Ad Muncher Keygen cracked by m101 for Phrozen Crew",0 ButtonText db "Generate Key",0 StartupString db "Please enter a name...",0 EditClassName db "edit",0 EditID equ 2 EditID2 equ 3 ButtonID equ 1 ButtonClassName db "button",0 IDM_GETTEXT equ 3 Serial2 db "FFFFFFFF" Serial db "BADC0DE-" buffer db 512 dup(?)

.data? hInstance HINSTANCE ? CommandLine LPSTR ? hwndButton HWND ? hwndEdit HWND ? hwndEdit2 HWND ? .code start: invoke GetModuleHandle, NULL mov hInstance,eax invoke GetCommandLine mov CommandLine,eax invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT invoke ExitProcess,eax WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD LOCAL wc:WNDCLASSEX LOCAL msg:MSG LOCAL hwnd:HWND mov wc.cbSize,SIZEOF WNDCLASSEX mov wc.style, CS_HREDRAW or CS_VREDRAW mov wc.lpfnWndProc, OFFSET WndProc mov wc.cbClsExtra,NULL mov wc.cbWndExtra,NULL push hInstance pop wc.hInstance mov wc.hbrBackground,COLOR_BTNFACE+1 mov wc.lpszMenuName,NULL mov wc.lpszClassName,OFFSET ClassName invoke LoadIcon,NULL,IDI_APPLICATION mov wc.hIcon,eax mov wc.hIconSm,eax invoke LoadCursor,NULL,IDC_ARROW mov wc.hCursor,eax invoke RegisterClassEx, addr wc INVOKE CreateWindowEx,WS_EX_CONTROLPARENT or DS_CENTER,ADDR ClassName,ADDR AppName,\

WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\ CW_USEDEFAULT,345,150,NULL,NULL,\ hInst,NULL mov hwnd,eax invoke ShowWindow, hwnd,SW_SHOWNORMAL invoke UpdateWindow, hwnd .WHILE TRUE invoke GetMessage, ADDR msg,NULL,0,0 .BREAK .IF (!eax) invoke TranslateMessage, ADDR msg invoke DispatchMessage, ADDR msg .ENDW mov eax,msg.wParam ret WinMain endp WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM .IF uMsg==WM_DESTROY invoke PostQuitMessage,NULL .ELSEIF uMsg==WM_CREATE invoke CreateWindowEx,WS_EX_CLIENTEDGE, ADDR EditClassName,NULL,\ WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT or\ ES_AUTOHSCROLL,\ 50,20,240,25,hWnd,EditID,hInstance,NULL mov hwndEdit,eax invoke CreateWindowEx,WS_EX_CLIENTEDGE, ADDR EditClassName,NULL,\ WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT or\ ES_AUTOHSCROLL or ES_READONLY,\ 50,45,240,25,hWnd,EditID2,hInstance,NULL mov hwndEdit2,eax invoke SetWindowText,hwndEdit2,ADDR StartupString invoke SetFocus, hwndEdit invoke CreateWindowEx,NULL, ADDR ButtonClassName,ADDR ButtonText,\ WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON,\ 80,75,180,25,hWnd,ButtonID,hInstance,NULL mov hwndButton,eax .ELSEIF uMsg==WM_COMMAND mov eax,wParam .IF lParam==0 .IF ax==IDM_GETTEXT push edi push esi invoke GetWindowText,hwndEdit,ADDR buffer,512 mov ebx, 0BADC0DEh lea esi, buffer xor ecx,ecx looksy: lodsb cmp al, 41h jl looksy2 cmp al, 5Ah

jg looksy2 add al, 20h looksy2: add ror add cmp jnz not mov mov mov shr mov mov lea xor ecx,eax ecx,08h ecx,ebx al, 0h looksy ecx eax,ecx [Serial2+3h],al [Serial2+2h],ah eax, 10h [Serial2+1h],al [Serial2],ah esi, Serial2 ecx,ecx

converter:

conv2:

xor ax,ax lodsb cmp ecx, 8h jl conv2 xor al, dl shl ax, 4h shr al, 4h cmp al, 0ah jl alpha add al, 37h jmp alphanumeric

alpha: alphanumeric:

add al, 30h cmp ah, 0ah jl alphab add ah, 37h jmp alphanumericb add ah, 30h mov [buffer+ecx], ah inc ecx mov [buffer+ecx], al inc ecx cmp ecx, 8h jl converter mov [buffer+ecx], 0h invoke SetWindowText,hwndEdit2,ADDR Serial pop esi pop edi .ELSE invoke DestroyWindow,hWnd .ENDIF .ELSE .IF ax==ButtonID shr eax,16

alphab: alphanumericb:

.IF ax==BN_CLICKED invoke SendMessage,hWnd,WM_COMMAND,IDM_GETTEXT,0 .ENDIF .ENDIF .ENDIF .ELSE invoke DefWindowProc,hWnd,uMsg,wParam,lParam ret .ENDIF xor eax,eax ret WndProc endp end start -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

There you have it, five minutes to find and work out the serial routine, another ten minutes for the keygen and youve created a keygen on-the-fly in fifteen minutes!