AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Subclassing einer fremden Application, warum funzt das net ?
Thema durchsuchen
Ansicht
Themen-Optionen

Subclassing einer fremden Application, warum funzt das net ?

Ein Thema von stoxx · begonnen am 9. Nov 2003 · letzter Beitrag vom 5. Sep 2008
Antwort Antwort
Seite 5 von 7   « Erste     345 67      
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#41

Re: Subclassing einer fremden Application, warum funzt das n

  Alt 10. Nov 2003, 23:56
Es ist eigentlich egal ob man MMF's nimmt oder nicht. Man könnte auch VirtualAllocEx() benutzten um einen Speicherbereich innerhalb eines anderen Processes zu injezieren. Man sollte nun zwei unterschiedliche Vorgehensweisen betrachten, abhängig ob Win9x oder Win2x.

Generell sähe es so aus:
1.) erzeuge einen Speicherbereich im Zielprozess
2.) initialisiere in diesem Speicher den Code + Datenstrukturen. In diesem Speicher liegt eine Threadfunktion und die WindowProc
3.) erzeuge einen Remote Thread, also einen Thread der im Zielprozess läuft. Unter Win2x gibts dafür CreateRemoteThread() unter Win9x kann man diese Funktion nachbauen.
4.) die Threadfunktion zeigt in unserem Speicherbereich

Nun ist es wichtig was die Threadfunktion überhaupt macht. Sie subclasses das betroffene Fensterhandle und setzt deren Fensterfunktion auf die Fensterfunktion in unserem Speicherbereich. Danach Terminiert sie den Thread.

Als Pseudocode sähe das so aus:

Delphi-Quellcode:
type
  PHookData = ^THookData;
  THookData = packed record
    SaveWindowProc: Pointer;
    hWnd: HWnd;
    GetWindowLong: function(hWnd, Index): Pointer: stdcall;
    SetWindowLong: function(hWnd, Index, Pointer): Bool; stdcall;
    ExitThread: procedure(Return); stdcall;
    CallWndProc: function(Proc, hWnd, wParam, lParam): lResult; stdcall;
    VirtualFree: fucntion(Pointer): Integer; stdcall;
    WindowProc: array[0..0] of Byte; // hier wird MyWndProc rein kopiert
    ThreadCode: array[0..0] of Byte; // hier wird ThreadProc hineinkopiert
  end;

function MyWndProc(...): Integer; stdcall;
var
  Memory: PHookData;
begin
  asm
     CALL @@1
@@1: POP EAX
     AND EAX,$FFFFF000 // align
     MOV Memory,EAX
  end;
  if Msg = wm_Destroy then
  begin
    Memory.CallWndProc(Memory.SaveWindowProc, hWnd, Msg, wParam, lParam);

 // hier Memory freigeben, wichtig dabei das der aktuelle Code ja in diesem Memory^ liegt
 // wir müssen also die Reücksrungadresse aus dem Stack holen. Dann Memory auf den Stack pushen
 // danach Rücksrungadresse pushen und einem Jump nach VirtualFree() durchführen.
 // Somit kehrt VirtualFree NICHT in unseren nun freigegebene Memory zurück, sondern zum
 // Aufrufer von MyWndProc().
    asm
      POP EDX
      MOV EAX,Memory
      PUSH EAX
      PUSH EDX
      JMP [EAX].VirtualFree
    end;
  end else
    if Msg = wm_Close then
    begin
    end else
      Result := Memory.CallWndProc(Memory.SaveWindowProc, Wnd, Msg, wParam, lParam);
end;

function ThreadProc(Memory: PHookData): Dword; stdcall;
// wichtig !! keine Aufrufe von Funktionen und Daten die nicht Importe/Inhalte in Memory sind !!
begin
  Memory.SaveWindowProc := Memory.GetWindowLong(Memory.hWnd, gwl_WndProc);
  Memory.SetWindowLong(Memory.hWnd, gwl_WindowProc, @Memory.WindowProc);
  Memory.ExitThread(0);
end;
 
procedure Subclass(hWnd);
var
  Memory: PHookData;
  ProcSize: Integer;
  ThreadFunc: Pointer;
begin
  ProcSize := PChar(@Subclass) - PChar(@MyWndProc);

  Memory := VirtualAllocEx(..., SizeOf(THookData) + ProcSize); // align on Pageboundary needed !!
  Move(@MyWndProc, @Memory.WindowProc, ProcSize);
  Memory.hWnd := hWnd;
  Memory.GetWindowLong := GetProcAddress();
  Memory.SetWindowLong := GetProcAddress();
  Memory.ExitThread := GetProcAddress();
  Memory.CallWndProc := GetProcAddress();
  Memory.VirtualFree := GetProcAddress();
  
  ThreadFunc := PChar(Memory) + SizeOf(THookData) + PChar(@ThreadProc) - PChar(@MyWndProc);
  
  CreateRemoteThread(..., ThreadFunc, Memory, ...);
end;
WICHTIG ! dies niemals mit dem integrierten Debugger testen, da BorDbk Importe im Prozess wie GetProcAddress() selber umbiegt. Somit kann zB. GetProcAddress(, 'GetWindowLong') eine Adresse zurückgeben die in den BorDbk zeigt statt in's Kernel/GDI. Am besten eine eigene GetProcAddress() Funktion benutzen die ohne API auskommt !.

Jetzt mus man nur noch zum hWnd das Process Handle und Process ID rausbekommen.

Gruß Hagen

PS: Den Feinschliff müsst ihr selber rausfinden, da dieses Posting so ziemlich der direkte Weg ist für schlaue Jungs.
  Mit Zitat antworten Zitat
Benutzerbild von stoxx
stoxx

Registriert seit: 13. Aug 2003
1.111 Beiträge
 
#42

Re: Subclassing einer fremden Application, warum funzt das n

  Alt 11. Nov 2003, 02:58
Hallo Hagen,

hab zwar noch nicht das Gefühl, dass ich das wirklich allein hinbekomme .. habe aber dennoch schonmal angefangen, Deinen Pseudocode umzuwandeln

Bis hierin bin ich gekommen, lässt sich aber nicht compilieren.

Bei dem Assembler Code sagt er mir in Zeile: JMP [EAX].VirtualFree
"Ungültige Kombination von Opcode und Operanden". ?

Hier der Quelltext:


Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type

  PHookData = ^THookData;
  THookData = packed record
    SaveWindowProc: Pointer;
    hWnd: HWnd;
    GetWindowLong: function(hWnd : HWND; nIndex : INTEGER ): LongInt; stdcall;
    SetWindowLong: function(hWnd : HWND; nIndex : INTEGER; wNewLong : LongInt): LongInt; stdcall;
    ExitThread: procedure(dwExitCode : DWORD); stdcall;
    CallWndProc: function(lpPrevWndFunc : TFNWndProc; hWnd: HWND; Msg: WORD; wParam: WPARAM; lParam: LPARAM): lResult; stdcall;
    VirtualFree: function(lpAddress : Pointer; dwSize : DWORD; dwFreeType : DWORD) : bool; stdcall; // richtige Parameter ?
    WindowProc: array[0..0] of Byte; // hier wird MyWndProc rein kopiert
    ThreadCode: array[0..0] of Byte; // hier wird ThreadProc hineinkopiert
  end;



  TForm1 = class(TForm)
    Button1: TButton;
  private

  public

  end;



var
  Form1: TForm1;

implementation

{$R *.dfm}


function MyWndProc(hWnd: HWND; Msg: WORD; wParam: WPARAM; lParam: LPARAM): lResult; stdcall;
var
  Memory: PHookData;
begin
  asm
     CALL @@1
@@1: POP EAX
     AND EAX,$FFFFF000 // align
     MOV Memory,EAX
  end;
  if Msg = wm_Destroy then
  begin
    Memory.CallWndProc(Memory.SaveWindowProc, hWnd, Msg, wParam, lParam);

// hier Memory freigeben, wichtig dabei das der aktuelle Code ja in diesem Memory^ liegt
// wir müssen also die Reücksrungadresse aus dem Stack holen. Dann Memory auf den Stack pushen
// danach Rücksrungadresse pushen und einem Jump nach VirtualFree() durchführen.
// Somit kehrt VirtualFree NICHT in unseren nun freigegebene Memory zurück, sondern zum
// Aufrufer von MyWndProc().
    asm
      POP EDX
      MOV EAX,Memory
      PUSH EAX
      PUSH EDX
      JMP [EAX].VirtualFree
    end;
  end else
    if Msg = wm_Close then
    begin
    end else
      Result := Memory.CallWndProc(Memory.SaveWindowProc, hWnd, Msg, wParam, lParam);
end;




end.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#43

Re: Subclassing einer fremden Application, warum funzt das n

  Alt 11. Nov 2003, 10:04
Delphi-Quellcode:
    asm
      JMP [EAX].THookData.VirtualFree
    end;
Wie gesagt, der Code lässt sich nicht so ohne weiteres direkt in Delphi umsetzen. Es gibt also noch ein paar Details zu beachten. Z.b. sind die Function Deklarationen der Windows API Funktionen nicht korrekt, sondern nur angedeutet.
Wichtig ist das VirtualAllocEx() einen an einer Speichergrenze von $1000 ausgerichteten Speicherbereich alloziert. Dies hat mehrere Gründe, der wichtigste ist aber wie im Assemblerpart von MyWndproc() am Anfang diese Speicheradresse ermittelt wird. Da alles dynamisch ist, auch für die Programmierung im Source, gibt es keine direkte und einfache Möglichkeit die korrekte Speicheradresse von Memory direkt der MyWndProc() zu übergeben. Diese Funktion muß also eine "Brute Force" Methode benutzen. Sie geht davon aus das Memory = $XXXXX000 ist.
Man könnte aber einen Dispatcher für MyWndProc() schreiben, d.h. eine kleine Assembler procedure vor MyWndProc() die einen zusätzlichen Parameter "Memory" in MyWndProc() einführt.

Delphi-Quellcode:
type
  PHookData = ^THookData;
  THookData = packed record
    ... bla bla
    case Integer of
     0: (WindowProc: array[0..0] of Byte);
     1: (WindowProc_POP_EDX: Byte;
         WindowProc_PUSH_CONST: Byte;
         WindowProc_Memory: Pointer);
  end;

function MyWndProc(): lResult; stdcall; forward;

procedure MyWndProcDispatch;
asm
      POP EDX
      PUSH $12345678
      PUSH EDX
      JMP MyWndProc
end;

function MyWndProc(Wnd: hWnd,....,lParam: LParam; Memory: PHookData): lResult; stdcall
begin
end;

procedure SubClassWnd();
begin
  ... blabla
  Move(@MyWndProcDispatch, Memory^, CodeSize);
  Memory.WindowProc_Memory := Memory;
  ... blabla
  Memory...... := ......
end;
Nun muß man bei VirtualAllocEx() nicht mehr auf die Ausrichtung des Speicherbereiches achten, da gezielt ein neuer Parameter in MyWndProc() eingeführt wird der die Adresse von Memory enthält.
Obige Vorgehensweise ist notwendig da der Delphi Linker alle Prozeduren auf 4 Bytes Grenzen ausrichtet, also optimiert. Es können also zwischen den Proceduren MyWndProcDispatch() und MyWndProc() und ThreadFunc() und SubClassWnd() Bytes im Code stehen, die nur Fillerbytes sind.
Da MyWndProc() aber von dir beliebig erweitert werden kann und auch soll, können wir nicht direkt den Code vom MyWndproc() in Memory patchen. Denn je nach dem was für lokale Variablen du benutzt ändert sich auch der Code den der Compiler als Stackframe automatisch ohne deinen Einfluß ändert.

gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#44

Re: Subclassing einer fremden Application, warum funzt das n

  Alt 11. Nov 2003, 10:21
Nachteile ? ja.

VirtualAllocEx() alloziert einen Speicher der sowohl im Zielprozess wie auch im eigenen Process zugänglich ist. Wenn die Speicheradresse von Memory im eigenen Prozess zB. $12345678 ist so heist dies NICHT zwangsläufig das diese Adresse auch im Zielprozess gleich $12345678 sein muß. Wir arbeiten ja in einem Protected Mode OS mit einem virtuellen Speichermanagement. Absolut transparent für uns könnte es also sein das Memory, obwohl es in beiden Prozesse zugreifbar ist, denoch an verschiedenen Adresse gemappt wird. Deshalb habe ich im ersten Posting den Trick mit dem ausgerichteten Speicher benutzt. Denn dadurch ermittelt der Code erst zur Laufzeit die korrekte und aktuell gültige Speicheradresse von Memory. Da Memory unseren Code enthält kann man zwangsläufig ausgehend vom gerade ausgeführten Code auf Memory zurückrechnen. Wir wissen aber nicht wie weit weg von der aktuellen Codeadresse der Anfang von Memory steht ! Deshalb ging mein Vorschlag von einem an einer Speichergrenze ausgerichteten Memory aus.

Generell sollte man bei solchen Tricks den sichersten Weg gehen und keinerlei Annahmen machen.

Gruß hagen
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#45

Re: Subclassing einer fremden Application, warum funzt das n

  Alt 11. Nov 2003, 10:35
Es gäbe aber einen sicheren Weg wenn man PHookData "umcodiert".

Delphi-Quellcode:
type
  PHookData = ^THookData;
  THookData = packed record
    WindowProc: array[0..511] of Byte;
    SaveWindowProc: Pointer;
    hWnd: HWnd;
    GetWindowLong: function(hWnd : HWND; nIndex : INTEGER ): LongInt; stdcall;
    SetWindowLong: function(hWnd : HWND; nIndex : INTEGER; wNewLong : LongInt): LongInt; stdcall;
    ExitThread: procedure(dwExitCode : DWORD); stdcall;
    CallWndProc: function(lpPrevWndFunc : TFNWndProc; hWnd: HWND; Msg: WORD; wParam: WPARAM; lParam: LPARAM): lResult; stdcall;
    VirtualFree: function(lpAddress : Pointer; dwSize : DWORD; dwFreeType : DWORD) : bool; stdcall;
  end;

function MyWndProc(hWnd: ... LParam, Memory): LResult; stdcall; forward;

procedure WndProcDispatcher;
asm
     CALL @@1
@@1: POP EAX
     SUB EAX,2 // Opcode size für CALL @@1, somit EAX = Memory
     POP EDX
     PUSH EAX
     PUSH EDX
     JMP MyWndProc
end;

function MyWndProc(... Memory: PHookData): LResult; stdcall;
const
  MemorySize = SizeOf(THookData);
begin
  if Msg = wm_Destroy then
  begin
    Memory.CallWndProc(Memory.SaveWindowProc, Msg, wParam, lParam);
    asm
       MOV EAX,Memory
       POP EDX
       PUSH EAX
       PUSH MemorySize
       PUSH 0
       PUSH EDX
       JMP [EAX].THookData.VirtualFree
    end;
  end .....
end;

procedure SubClassWnd;
begin
...
  Memory := VirtualAllocEx(..., SizeOf(THookData), ...);
  Move(@WndProcDispatcher, Memory^, CodeSize);
...
end;
Nun ist es so das der Code für WndProcDispatcher + MyWndproc + ThreadFunc gleich am Anfang von Memory gespeichert wird. Da wir aber nicht die exakte Codegröße für diese Funktionen kennen reservieren wir 512 Bytes dafür. Es kann nun passieren das der Code größer als 512 Bytes wird und dies ist gefährlich. Dafür können wird auf einfache Weise die Adresse für Memory in WndProcDispatcher dynamisch an Hand der Adresse des ausgeführten Codes ermitteln.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von stoxx
stoxx

Registriert seit: 13. Aug 2003
1.111 Beiträge
 
#46

Re: Subclassing einer fremden Application, warum funzt das n

  Alt 11. Nov 2003, 13:45
der WndProcDispatcher braucht doch sicherlich dieselben Parameter, wie MyWndProc oder ?

function WndProcDispatcher (hWnd: HWND; Msg: WORD; wParam: WPARAM; lParam: LPARAM): lResult; stdcall;


der Aufruf mit Setwindowlong sähe dann so aus ?

Memory.SetWindowLong(Memory.hWnd, gwl_WindowProc, @Memory.WndProcDispatcher); ?


oder ist das falsch ?
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#47

Re: Subclassing einer fremden Application, warum funzt das n

  Alt 11. Nov 2003, 17:27
Zitat:
der WndProcDispatcher braucht doch sicherlich dieselben Parameter, wie MyWndProc oder ?
Nein, auf gar keinen Fall. Er hat zwar diese Aufrufparamter aber du solltest sie NICHT deklarieren. Es ist dann nämlich durchaus möglich das der Compiler einen Stackframe, auch für den Assemblercode, anlegt. Da wir im Assemblerpart direkt den Stack manipulieren würde dies zu Abstürtzen führen. Also: WindowProcDispatcher so lassen wie er ist.

Zitat:
function MyWndProc(hWnd: HWND; Msg: WORD; wParam: WPARAM; lParam: LPARAM; Memory: PHookData): lResult; stdcall;
Ist richtig, da unser WindowProcDispatcher() ja den letzten Parameter Memory in die Parameterlist hinzufügt.

Zitat:
Memory.SetWindowLong(Memory.hWnd, gwl_WindowProc, @Memory.WndProcDispatcher); ?
Richtig. Oder besser,

Memory.SetWindowLong(Memory.hWnd, gwl_WindowProc, Memory); da im letzten meiner Beispiele der Dispatcher am Anfang von Memory steht.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von stoxx
stoxx

Registriert seit: 13. Aug 2003
1.111 Beiträge
 
#48

Re: Subclassing einer fremden Application, warum funzt das n

  Alt 12. Nov 2003, 04:18
Hallo Hagen,

ich komme hier echt nicht weiter.
Mein Problem ist, dass ich noch nie irgendwas in Assembler programmiert habe.
Auch habe ich von Befehlen wie : VirtualAllocEx heute das erste mal gehört, und habe weder mit diesen Funktionen gearbeitet, noch wüsste ich sie einzusetzen.
Geschweige denn, die richtigen Parameter zu verwenden.
Ehrlich gesagt bin ich nicht davon überzeugt, dass man mit meinem Wissen aus Deinen Hinweisen einen funktionierenden Code schreiben kann.

Um noch ehrlicher zu sein, ich bekomms alleine nicht hin und bräuchte die fertige Lösung.
... also im Moment bin ich am Ende mit meinem Latein


Code:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type

  PHookData = ^THookData;
  THookData = packed record
    WindowProc: array[0..511] of Byte;
    ThreadCode: array[0..511] of Byte;

   
    SaveWindowProc: Pointer;
    hWnd: HWnd;
    GetWindowLong: function(hWnd : HWND; nIndex : INTEGER ): LongInt; stdcall;
    SetWindowLong: function(hWnd : HWND; nIndex : INTEGER; wNewLong : LongInt): LongInt; stdcall;
    ExitThread: procedure(dwExitCode : DWORD); stdcall;
    CallWndProc: function(lpPrevWndFunc : TFNWndProc; hWnd: HWND; Msg: WORD; wParam: WPARAM;  
      lParam: LPARAM): lResult; stdcall;
    VirtualFree: function(lpAddress : Pointer; dwSize : DWORD; dwFreeType : DWORD) : bool;  
      stdcall;

  end;



  TForm1 = class(TForm)
    Button1: TButton;
  private

  public

  end;



var
  Form1: TForm1;

implementation

{$R *.dfm}


function MyWndProc(hWnd: HWND; Msg: WORD; wParam: WPARAM; lParam: LPARAM): LResult; stdcall; forward;

////////////////////////////////////////////////////////////////////////////////

procedure WndProcDispatcher;
asm
     CALL @@1 
@@1: POP  EAX
     SUB  EAX,2    //  Opcode size für CALL @@1, somit EAX = Memory
     POP  EDX
     PUSH EAX
     PUSH EDX
     JMP  MyWndProc
end;

/////////////////////////////////////////////////////////////////////////////////

function MyWndProc(hWnd: HWND; Msg: WORD; wParam: WPARAM; lParam: LPARAM): lResult; stdcall;
const
  MemorySize = SizeOf(THookData );
var
  Memory: PHookData;
begin

  if Msg = wm_Destroy then
  begin
    Memory.CallWndProc(Memory.SaveWindowProc, hWnd, Msg, wParam, lParam);
    asm
      MOV EAX,Memory
       POP EDX
       PUSH EAX
       PUSH MemorySize
       PUSH 0
       PUSH EDX
       JMP [EAX].THookData.VirtualFree

    end;
  end else
    if Msg = wm_Close then
    begin
    end else
      Result := Memory.CallWndProc(Memory.SaveWindowProc, hWnd, Msg, wParam, lParam);
end;

/////////////////////////////////////////////////////////////////////////////////

function ThreadProc(Memory: PHookData): Dword; stdcall;
begin
  Memory.SaveWindowProc := Pointer ( Memory.GetWindowLong(Memory.hWnd, gwl_WndProc) );
  Memory.SetWindowLong(Memory.hWnd, gwl_WndProc, Memory.WndProcDispatcher);
  Memory.ExitThread(0);
end;

/////////////////////////////////////////////////////////////////////////////////

procedure SubClassWnd(hWnd);
var
  Memory: PHookData;
  ProcSize: Integer;
  ThreadFunc: Pointer;

begin
  ProcSize := PChar(@Subclass) - PChar(@MyWndProc);
  Memory := VirtualAllocEx(..., SizeOf(THookData), ...);
  Move(@WndProcDispatcher, Memory^, ProcSize);
  Memory.hWnd := hWnd;

   ???

end;


end.
  Mit Zitat antworten Zitat
DaFox

Registriert seit: 1. Aug 2003
Ort: Kippenheim
90 Beiträge
 
#49

Re: Subclassing einer fremden Application, warum funzt das n

  Alt 13. Nov 2003, 01:22
Hagen,

darf ich mal ganz frech fragen, ob Du selbst auf diese Methode gekommen bist oder ob Du von Jeffrey Richter inspiriert wurdest? Richter erklärt nämlich in seinem Buch genau die gleiche Methode! Rein theoretisch natürlich und er schließt diesen Ausflug in die Theorie auch mit "Leider habe ich dazu aber kein Beispiel"
Wenn es auf Deinem Mist gewachsen ist und Du also den gleichen Einfall wie er hattest, solltest Du dich mal daran machen ein Buch zu schreiben!

Gruß,
Markus
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#50

Re: Subclassing einer fremden Application, warum funzt das n

  Alt 13. Nov 2003, 01:51
Ich hatte mit Luckie schon das Vergnügen über Richter zu diskutieren. Und ich habe von ihm gehört, kenne aber keines seiner Bücher. Warum auch ? Die Ideen und angedeuteten Umsetzungen findest du überall im WEB. Auch ich werde hier NUR andeuten und nur die richtige Richtung wie es funktionieren wird, aufzeigen. Warum ? Man muß sich selber reinpfriemeln und kann eigentlich NUR dadurch auch alles selber kapieren und verstehen lernen. Eine Presentation der fertigen Lösung ist also falsch. Grundsätzlich ist es doch so, ohne arrogant erscheinen zu wollen, "ich weiß wie es geht und habe es gecodet" das reicht mir eigentlich.

Appropo Bücher schreiben:
1.) als Geschichtenerzähler tauge ich nichts, und meine Ausdruckweise
2.) während ein Buchautor Zeit verschwendet um nach Informationen zu suchen, seine Sätze gut zu formulieren und noch Grafiken beipackt, sitze ich am Rechner und erweitere mein Wissen.
3.) Buchautoren schreiben also gute Bücher, und sie sind sehr wertvoll um sich in eine Materie einzuarbeiten. Will man mehr, dann gibt es keine Lehrer mehr die einem was beibringen können, und man muß mehr Wissen als der Buchautor erlangen.
4.) Wissen in der Programmierung ist eine Kombination aus theoretischem Wissen und praktischer Umsetzung. Ich halte Programmieren für ein Handwerk und die vielen unfähigen Dr. Informatiker der Universitäten beweisen dies leider immer wieder. (autsch)
Ähnliches trifft auf Buchautoren zu, wir als Leser verlangen das Unmögliche von ihnen: sehr breites Informationsfeld mit bis ins kleinste beschriebenen Details und fertigen hocheffizienten Beispielen. Dies kann ein Buch der Programmierung heutzutage nicht mehr liefern.

Gruß Hagen
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 5 von 7   « Erste     345 67      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:33 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz