| Autor |
Beitrag |
scrooge
      
Beiträge: 200
|
Verfasst: Sa 24.07.04 19:21
Hi,
hab seit längerer Zeit ein Prog namens "inmemexe" afu meinem Computer liegen.
Das Programm sartet sich sebst neu und ändert dann seinen Code in den einer Resource (Resource ist eine andere Exe (soweit ich mir das denken kann), die eine Proc innerhalb einer Dll aufruft).
Hab mir jetzt mal endlich nach langer Zeit mal Pe-Format angeguckt und kapiers soweit.
Gibt nur noch eine Codezeile die ich nicht ganz raffe:
Delphi-Quelltext 1: 2: 3: 4:
| Context.ContextFlags := CONTEXT_INTEGER; if GetThreadContext(ProcessInfo.hThread, Context) and ReadProcessMemory(ProcessInfo.hProcess, Pointer(Context.Ebx + 8), @BaseAddress, SizeOf(BaseAddress), BytesRead) |
Schon mal danke für die Mühe
|
|
obbschtkuche
Gast
Erhaltene Danke: 1
|
Verfasst: Sa 24.07.04 19:29
EBX ist ein "general purpose register". Vermutlich liegt darin eine Variable oder ein Parameter...
Stackpointer ist ESP (Extended[?] Stack Pointer)
|
|
raziel
      
Beiträge: 2453
Arch Linux
JS (WebStorm), C#, C++/CLI, C++ (VS2013)
|
Verfasst: Sa 24.07.04 19:39
EBX wird im allgemeinen Base Register genannt, hat aber mit dem Stack recht wenig zu tun. Was Du meinst ist EBP, der zum Sichern des Stackframe beim Eintritt in Funktionen dient, wenn Parameter und/oder lokale Variablen benötigt werden.
Es gibt als General Purpose Register noch EAX (Accumulator Register), ECX (Counter Register) und EDX (Data-Register). Man kann sie aber i.a. füllen mit was man will, deshalb wäre mehr Code interessant und vor allem wäre interessant, wozu das Ganze gut sein soll!
raziel
_________________ JSXGraph
|
|
FAlter
      
Beiträge: 192
Win XP Home
Turbo Delphi 2006 (Win32), C# (VS 2008 Prof.), Java (Eclipse), PHP
|
Verfasst: Sa 24.07.04 21:04
Soweit, so gut. Um jetzt noch die richtige Reihenfolge zu nennen: EAX, ECX, EDX, EBX
Das E weist auf 32-Bit hin (könnte wirklick Extended heißen oder Expanded). Bei 16 Bit einfach AX etc. verwenden. Hier mal 'ne Grafik für die Zusammenhänge:
Quelltext 1: 2: 3: 4:
| 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------EAX+ +---------------------------------------------AX+ +---------------------AH+ +-------------------AL+ |
Bits 0 - 31 sind das EAX-Register. Die Bits 0 - 15 sind gleichzeitig auch AX, welches wiederum in AL (0 - 7) und AH (8 - 15) unterteilt ist.
Genauso auch bei den anderen auch.
EBX lässt sich zum adressieren verwenden. Wobei man SEGMENT:BASIS addressiert und EBX stellt eben diese Basis dar (meistens DS:EBX). Darum E BX.
ESP (oder SP bei 16-Bit, gibt kein SH/SL) addressiert genauso, jedoch addressiert es das unterste Element des Stacks (SS:ESP). Bei PUSH wird ESP um 4 verringert und der Wert an die neue Position geschrieben.
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: So 25.07.04 04:41
| FAlter hat folgendes geschrieben: | | Soweit, so gut. Um jetzt noch die richtige Reihenfolge zu nennen: EAX, ECX, EDX, EBX |
lol ... srry, aber das ist so falsch...
Richtiger wäre:
EAX EDX ECX (EBX)*
Laut meiner Dokumentation zum Thema Assembler (gibt's unter webster.cs.ucr.edu/index.html zum DL):
| Meine verwendete ASM Referenze zum Thema Parameter-Übergabe hat folgendes geschrieben: | Parameters are transferred to procedures and functions via CPU registers or the stack, depending on the routine’s calling convention. For information about calling conventions, see Calling conventions.
Variable (var) parameters are always passed by reference, as 32-bit pointers that point to the actual storage location.
Value and constant (const) parameters are passed by value or by reference, depending on the type and size of the parameter:
An ordinal parameter is passed as an 8-bit, 16-bit, 32-bit, or 64-bit value, using the same format as a variable of the corresponding type.
A real parameter is always passed on the stack. A Single parameter occupies 4 bytes, and a Double, Comp, or Currency parameter occupies 8 bytes. A Real48 occupies 8 bytes, with the Real48 value stored in the lower 6 bytes. An Extended occupies 12 bytes, with the Extended value stored in the lower 10 bytes.
A short-string parameter is passed as a 32-bit pointer to a short string.
A long-string or dynamic-array parameter is passed as a 32-bit pointer to the dynamic memory block allocated for the long string. The value nil is passed for an empty long string.
A pointer, class, class-reference, or procedure-pointer parameter is passed as a 32-bit pointer.
A method pointer is passed on the stack as two 32-bit pointers. The instance pointer is pushed before the method pointer so that the method pointer occupies the lowest address.
Under the register and pascal conventions, a Variant parameter is passed as a 32-bit pointer to a Variant value.
Sets, records, and static arrays of 1, 2, or 4 bytes are passed as 8-bit, 16-bit, and 32-bit values. Larger sets, records, and static arrays are passed as 32-bit pointers to the value. An exception to this rule is that records are always passed directly on the stack under the cdecl, stdcall, and safecall conventions; the size of a record passed this way is rounded upward to the nearest double-word boundary.
An open-array parameter is passed as two 32-bit values. The first value is a pointer to the array data, and the second value is one less than the number of elements in the array.
When two parameters are passed on the stack, each parameter occupies a multiple of 4 bytes (a whole number of double words). For an 8-bit or 16-bit parameter, even though the parameter occupies only a byte or a word, it is passed as a double word. The contents of the unused parts of the double word are undefined.
Under the pascal, cdecl, stdcall and safecall conventions, all parameters are passed on the stack. Under the pascal convention, parameters are pushed in the order of their declaration (left-to-right), so that the first parameter ends up at the highest address and the last parameter ends up at the lowest address. Under the cdecl, stdcall, and safecall conventions, parameters are pushed in reverse order of declaration (right-to-left), so that the first parameter ends up at the lowest address and the last parameter ends up at the highest address.
Under the register convention, up to three parameters are passed in CPU registers, and the rest (if any) are passed on the stack. The parameters are passed in order of declaration (as with the pascal convention), and the first three parameters that qualify are passed in the EAX, EDX, and ECX registers, in that order. Real and method-pointer types do not qualify as register parameters, but all other parameters do. If more than three parameters qualify as register parameters, the first three are passed in EAX, EDX, and ECX, and the remaining parameters are pushed onto the stack in order of declaration. For example, given the declaration
procedure Test(A: Integer; var B: Char; C: Double; const D: string; E: Pointer);
a call to Test passes A in EAX as a 32-bit integer, B in EDX as a pointer to a Char, and D in ECX as a pointer to a long-string memory block; C and E are pushed onto the stack as two double-words and a 32-bit pointer, in that order.
Register saving conventions
Procedures and functions must preserve the EBX, ESI, EDI, and EBP registers, but can modify the EAX, EDX, and ECX registers. When implementing a constructor or destructor in assembler, be sure to preserve the DL register. Procedures and functions are invoked with the assumption that the CPU’s direction flag is cleared (corresponding to a CLD instruction) and must return with the direction flag cleared. |
| FAlter hat folgendes geschrieben: | | EBX lässt sich zum adressieren verwenden. Wobei man SEGMENT:BASIS addressiert und EBX stellt eben diese Basis dar (meistens DS:EBX). Darum EBX. |
Bei 32-Bit-Assembler geht das aber auch mit jedem anderem Register, wenn man im aktuellen Segment bleibt:
Delphi-Quelltext 1: 2: 3: 4: 5:
| asm mov EDX, EAX xor EAX, EAX mov [EDX-$00000004], EAX end; |
(Der Code cleart (IIRC) die Funktionsadresse des Destructors des Objects Self. Gibt beim Freigeben dann ne Exception (AV um genau zu sein).
| FAlter hat folgendes geschrieben: | | ESP (oder SP bei 16-Bit, gibt kein SH/SL) addressiert genauso, jedoch addressiert es das unterste Element des Stacks (SS:ESP). Bei PUSH wird ESP um 4 verringert und der Wert an die neue Position geschrieben. |
Yip. POP funktioniert genau andersrum:
Wert einlesen und dann (E)SP inkrementieren:
Delphi-Quelltext 1: 2: 3: 4:
| asm mov reg, [ESP] inc ESP, 4 end; |
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
scrooge 
      
Beiträge: 200
|
Verfasst: So 25.07.04 16:41
Danke für die ausführliche Berichtigung
Hier mal der ganze Code:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99:
| program InMemExe;
uses Windows, ntddk in 'ntddk.pas';
{$R res\Image.res}
function Protect(Characteristics: ULONG): ULONG; const Mapping: array [0..7] of ULONG = ( PAGE_NOACCESS, PAGE_EXECUTE, PAGE_READONLY, PAGE_EXECUTE_READ, PAGE_READWRITE, PAGE_EXECUTE_READWRITE, PAGE_READWRITE, PAGE_EXECUTE_READWRITE ); begin Result := Mapping[Characteristics shr 29]; end;
type PImageSectionHeaders = ^TImageSectionHeaders; TImageSectionHeaders = array [0..95] of TImageSectionHeader; var ProcessInfo: TProcessInformation; StartupInfo: TStartupInfo; Success: Boolean; Context: TContext; BaseAddress: Pointer; BytesRead: DWORD; Resource: Pointer; NtHeaders: PImageNtHeaders; BytesWritten: DWORD; Sections: PImageSectionHeaders; i: ULONG; OldProtect: ULONG; begin FillChar(StartupInfo, SizeOf(TStartupInfo), 0); StartupInfo.cb := SizeOf(TStartupInfo); if CreateProcess(nil, PChar(ParamStr(0)), nil, nil, False, CREATE_SUSPENDED, nil, nil, StartupInfo, ProcessInfo) then begin Success := False; try Context.ContextFlags := CONTEXT_INTEGER; if GetThreadContext(ProcessInfo.hThread, Context) and ReadProcessMemory(ProcessInfo.hProcess, Pointer(Context.Ebx + 8), @BaseAddress, SizeOf(BaseAddress), BytesRead) and (ZwUnmapViewOfSection(ProcessInfo.hProcess, BaseAddress) >= 0) then begin Resource := LockResource( LoadResource(0, FindResource(0, 'Image', 'EXE'))); if Assigned(Resource) then begin NtHeaders := PImageNtHeaders( Cardinal(Resource) + Cardinal(PImageDosHeader(Resource)._lfanew)); BaseAddress := ntddk.VirtualAllocEx(ProcessInfo.hProcess, Pointer(NtHeaders.OptionalHeader.ImageBase), NtHeaders.OptionalHeader.SizeOfImage, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE); if Assigned(BaseAddress) and WriteProcessMemory(ProcessInfo.hProcess, BaseAddress, Resource, NtHeaders.OptionalHeader.SizeOfHeaders, BytesWritten) then begin Sections := PImageSectionHeaders(ImageFirstSection(NtHeaders)); for i := 0 to NtHeaders.FileHeader.NumberOfSections - 1 do if WriteProcessMemory(ProcessInfo.hProcess, Pointer(Cardinal(BaseAddress) + Sections[i].VirtualAddress), Pointer(Cardinal(Resource) + Sections[i].PointerToRawData), Sections[i].SizeOfRawData, BytesWritten) then ntddk.VirtualProtectEx(ProcessInfo.hProcess, Pointer(Cardinal(BaseAddress) + Sections[i].VirtualAddress), Sections[i].Misc.VirtualSize, Protect(Sections[i].Characteristics), OldProtect); if WriteProcessMemory(ProcessInfo.hProcess, Pointer(Context.Ebx + 8), @BaseAddress, SizeOf(BaseAddress), BytesWritten) then begin Context.Eax := ULONG(BaseAddress) + NtHeaders.OptionalHeader.AddressOfEntryPoint; Success := SetThreadContext(ProcessInfo.hThread, Context); end; end; end; end; finally if not Success then TerminateProcess(ProcessInfo.hProcess, 0) else ResumeThread(ProcessInfo.hThread); CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); end; end; end. |
ntddk enthält die nativen Api's.
// PS: E bedeutet Extended
|
|
|