c c O function GetHDDSerialNumber(NomDrive:byte) : String; const IDENTIFY_BUFFER_SIZE = 512; type TIDERegs = packed record bFeaturesReg : BYTE; // Used for specifying SMART "commands". bSectorCountReg : BYTE; // IDE sector count register bSectorNumberReg : BYTE; // IDE sector number register bCylLowReg : BYTE; // IDE low order cylinder value bCylHighReg : BYTE; // IDE high order cylinder value bDriveHeadReg : BYTE; // IDE drive/head register bCommandReg : BYTE; // Actual IDE command. bReserved : BYTE; // reserved for future use. Must be zero. end; TSendCmdInParams = packed record // Buffer size in bytes cBufferSize : DWORD; // Structure with drive register values. irDriveRegs : TIDERegs; // Physical drive number to send command to (0,1,2,3). bDriveNumber : BYTE; bReserved : Array[0..2] of Byte; dwReserved : Array[0..3] of DWORD; bBuffer : Array[0..0] of Byte; // Input buffer. end; TIdSector = packed record wGenConfig : Word; wNumCyls : Word; wReserved : Word; wNumHeads : Word; wBytesPerTrack : Word; wBytesPerSector : Word; wSectorsPerTrack : Word; wVendorUnique : Array[0..2] of Word; sSerialNumber : Array[0..19] of CHAR; wBufferType : Word; wBufferSize : Word; wECCSize : Word; sFirmwareRev : Array[0..7] of Char; sModelNumber : Array[0..39] of Char; wMoreVendorUnique : Word; wDoubleWordIO : Word; wCapabilities : Word; wReserved1 : Word; wPIOTiming : Word; wDMATiming : Word; wBS : Word; wNumCurrentCyls : Word; wNumCurrentHeads : Word; wNumCurrentSectorsPerTrack : Word; ulCurrentSectorCapacity : DWORD; wMultSectorStuff : Word;
ulTotalAddressableSectors : DWORD; wSingleWordDMA : Word; wMultiWordDMA : Word; bReserved : Array[0..127] of BYTE; end; PIdSector = ^TIdSector; TDriverStatus = packed record // Error code from driver, or 0 if no error. bDriverError : Byte; // Contents of IDE Error register. Only valid when bDriverError is SMART_IDE_ERROR. bIDEStatus : Byte; bReserved : Array[0..1] of Byte; dwReserved : Array[0..1] of DWORD; end; TSendCmdOutParams = packed record // Size of bBuffer in bytes cBufferSize : DWORD; // Driver status structure. DriverStatus : TDriverStatus; // Buffer of arbitrary length in which to store the data read from the drive. bBuffer : Array[0..0] of BYTE; end; var hDevice : THandle; cbBytesReturned : DWORD; // ptr : PChar; SCIP : TSendCmdInParams; aIdOutCmd : Array [0..(SizeOf(TSendCmdOutParams)+IDENTIFY_BUFFER_SIZE-1)-1] of Byte; IdOutCmd : TSendCmdOutParams absolute aIdOutCmd;
procedure ChangeByteOrder( var Data; Size : Integer ); var ptr : PChar; i : Integer; c : Char; begin ptr := @Data; for i := 0 to (Size shr 1)-1 do begin c := ptr^; ptr^ := (ptr+1)^; (ptr+1)^ := c; Inc(ptr,2); end; end; const IdeDriveNom='\\.\PhysicalDrive'; begin Result :='Error'; // return empty string on error
if SysUtils.Win32Platform=VER_PLATFORM_WIN32_NT then // Windows NT, Windows 2000 begin // warning! change name for other drives: ex.: second drive '\\.\PhysicalDrive1\' hDevice := CreateFile( PChar(IdeDriveNom+IntToStr(NomDrive)),{'\\.\PhysicalDrive0'} GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 ); end else // Version Windows 95 OSR2, Windows 98 hDevice := CreateFile( '\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0 ); if hDevice=INVALID_HANDLE_VALUE then Exit; try FillChar(SCIP,SizeOf(TSendCmdInParams)-1,#0); FillChar(aIdOutCmd,SizeOf(aIdOutCmd),#0); cbBytesReturned := 0; // Set up data structures for IDENTIFY command. with SCIP do begin cBufferSize := IDENTIFY_BUFFER_SIZE; // bDriveNumber := 0; with irDriveRegs do begin bSectorCountReg := 1; bSectorNumberReg := 1; // if Win32Platform=VER_PLATFORM_WIN32_NT then bDriveHeadReg := $A0 // else bDriveHeadReg := $A0 or ((bDriveNum and 1) shl 4); bDriveHeadReg := $A0; bCommandReg := $EC; end; end; if not DeviceIoControl( hDevice, $0007c088, @SCIP, SizeOf(TSendCmdInParams)-1, @aIdOutCmd, SizeOf(aIdOutCmd), cbBytesReturned, nil ) then Exit; finally CloseHandle(hDevice); end; with PIdSector(@IdOutCmd.bBuffer)^ do begin ChangeByteOrder( sSerialNumber, SizeOf(sSerialNumber) ); (PChar(@sSerialNumber)+SizeOf(sSerialNumber))^ := #0; Result := PChar(@sSerialNumber); end; end;
3á á procedure TForm1.btnGetHDinfoClick(Sender: TObject); var getHDSerial : string; begin getHDSerial := GetHDDSerialNumber(0);
end;
V á ShowMessage( GetHDDSerialNumber(0));
| function GetHardDiskSerial(const DriveLetter: char): string; var NotUsed : dWord; VolumeFlags : dWord; VolumeInfo : array[0..MAX_PATH] of char; VolumeSerialNumber: dWord; begin GetVolumeInformation(PChar(DriveLetter + ':\'), VolumeInfo, SizeOf(VolumeInfo), @VolumeSerialNumber, NotUsed, VolumeFlags, nil, 0); result := Format('%14s | %X |', [VolumeInfo, VolumeSerialNumber]) // result := IntToStr(VolumeSerialNumber); end;
| | | | ! |
"
! #$%
Ê $ | & ÊÊ unit Patcher; { { { { {
Patcher Unit V1.0.0.0 - Patcher.pas } Copyright 2008 Joonas905 / JaX2JoN50. } You can freely use, edit or redistribute this unit, } but this copyright notice must remain. } Unit comes with absolutely NO WARRANTY! }
interface uses SysUtils; type ByteArray = Array of Byte; TPatches = Array of Record Offset: Cardinal; Bytes: ByteArray; end; TPatcher = class private fInit: Boolean; fHandle: Integer; public constructor Create( FileName: String ); destructor Destroy; override; procedure Add( Offset: Cardinal; Bytes: ByteArray ); procedure PatchFile; end; implementation var Patches: TPatches; constructor TPatcher.Create( FileName: String ); begin fInit := False; if FileExists( FileName ) = True then begin inherited Create; fHandle := FileOpen( FileName, fmOpenReadWrite ); if fHandle <> -1 then fInit := True;
end; end; destructor TPatcher.Destroy; begin if fInit = True then begin fInit := False; FileClose( fHandle ); SetLength( Patches, 0 ); inherited Destroy; end; end; procedure TPatcher.Add( Offset: Cardinal; Bytes: ByteArray ); var Size: Cardinal; begin if fInit = True then begin Size := Length( Patches ); SetLength( Patches, Size + 1 ); Patches[Size].Offset := Offset; Patches[Size].Bytes := Bytes; end; end; procedure TPatcher.PatchFile; var I, X, Size: Cardinal; Line: String; begin if fInit = True then begin Size := Length( Patches ); if Size > 0 then begin for I := 0 to ( Size - 1 ) do begin FileSeek( fHandle, Patches[I].Offset, 0 ); Line := String( Patches[I].Bytes ); for X := 1 to ( Length( Line ) - 1 ) do FileWrite( fHandle, Line[X], 1 ); end; SetLength( Patches, 0 ); end; end; end; end.
Ê unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Patcher; type TForm1 = class(TForm) Button1: TButton; end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click( Sender: TObject ); var Patcher: TPatcher; Bytes: ByteArray; begin // Set length SetLength( Bytes, 2 ); Bytes[0] := $90; // NOP Bytes[1] := $90; // NOP // Let's create a patcher instance Patcher := TPatcher.Create( {Filename here} ); // Add few patches to be made // Patcher.Add( {Offset}, {Bytes} ); Patcher.Add( 0, Bytes ); // And we patch Patcher.PatchFile; // Finally destroy Patcher.Destroy; end; end.
#'( )$* :0041403D eax, eax ; eax=length of serial :0041403F jne 0041407 ; if not zero, jump to 00414079 :00414041 push 00000010 ; else... :00414043 push 0042490C; push error messages :00414048 push 004248BC ; for .. :0041404D push ebp :0041404E Call dword ptr [004202AC] ; .. Message :00414054 push 00000471 :00414059 push ebp :0041405A Call dword ptr [004202B0] :00414060 push eax :00414061 Call dword ptr [004202B4] :00414067 mov eax, 00000001 ; eax=1 => bad :0041406C pop edi ; stack :0041406D pop esi :0041406E pop ebp :0041406F pop ebx :00414070 add esp, 00000784 :00414076 ret 0010 ; leave call with eax=1 :00414079 mov ebx, dword ptr [004202F4] ; we land if serial is entered :0041407F lea edx, dword ptr [esp+14] ; edx=name :00414083 push edx :00414084 lea eax, dword ptr [esp+6C]; eax=first name :00414088 push 00422170 ; push 'HappyIcon' (constant) :0041408D push eax :0041408E lea ecx, dword ptr [esp+5A0] :00414095 push 004248B4 ; push '%s%s%s' :0041409A push ecx :0041409B call ebx ; this make our new string :0041409D lea edi, dword ptr [esp+5A8] ; and move it to edi :004140A4 or ecx, FFFFFFFF :004140A7 xor eax, eax :004140A9 add esp, 00000014 :004140AC repnz :004140AD scasb :004140AE not ecx :004140B0 sub edi, ecx :004140B2 lea edx, dword ptr [esp+00000190] :004140B9 mov eax, ecx :004140BB mov esi, edi :004140BD mov edi, edx :004140BF shr ecx, 02 :004140C2 repz :004140C3 movsd :004140C4 mov ecx, eax :004140C6 lea eax, dword ptr [esp+190] ; new string to eax :004140CD and ecx, 00000003 :004140D0 repz :004140D1 movsb :004140D2 mov cl, byte ptr [esp+190]; CALCULATION BEGINS HERE :004140D9 test cl, cl ; cl=ascii of first char :004140DBje 004140FC; if there's no ascii jmp :004140DD; cmp byte ptr [eax], 5F; cmp ascii with 5Fh ('_') :004140E0 jne 004140E5 ; if so, ...
:004140E2 :004140E5 :004140E8 :004140EC :004140F2 :004140F3 :004140F7 :004140FA :004140FC :00414103 :00414104 :00414109 to ecx :0041410D :00414110 2468BDF0h :00414116 ecx) :00414118
mov byte ptr [eax], 20 ; ascii is 20h (' ') movsx ecx, byte ptr [eax] ; ascii to ecx xor ecx, dword ptr [esp+10] ; xor ecx with [esp+10] xor ecx, 13579ACE ; xor ecx with 13579ACEh inc eax ; eax(name) + 1 (next char) mov dword ptr [esp+10], ecx ; [esp+10] = ecx cmp byte ptr [eax], 00; cmp name with 00 .. LOOP jne 004140DD if there're some chars, jump back .. LOOP lea edx, dword ptr [esp+0BC] ; serial to edx push edx call 0041637C ; serial test (if avaible etc.) mov ecx, dword ptr [esp+14]; mov [esp+10] (from calculation) add esp, 00000004 xor ecx, 2468BDF0
; xor ecx (= [esp+10]) with
cmp eax, ecx
; cmp serial(? eax) with real(?
je 00414148
uses crt; var name, fname, endname: string ecx, i : longint; esp: longword; code begin writeln('KeyGen for 3ds max 9 by FureiYa'); writeln; write('Name: '); readln(name); write('First Name: '); readln(fname); endname:= fname, 'Autodesk', name; esp:= $FFFFFFFF; For i:= 1 to length(endname) do begin ecx:= ord(endname[i]); If ecx = $5F then ecx:= $20; ecx:= ecx ord esp; ecx:= ecx ord $13579ACE; esp:= ecx; end; esp:= esp xor $2468BDF0; writeln('Serial: ', esp); end.
; ; ; ; ; ;
standart declare variables all strings register as longint MUST BE longword ... or you get negative
; code start ; Text=xGenerate ; read in your name ; read in first name ; make string ; first value of esp ; start loop ;\ ; \ ; > Calculation ; / ;/ ; xor loop result ; post serial