首页
社区
课程
招聘
关于如何在RING3层防止截取键盘输入
2010-12-20 11:49 10998

关于如何在RING3层防止截取键盘输入

2010-12-20 11:49
10998
截取键盘输入的一般方法是:通过SetWindowsHookEx安装一个全局的消息钩子(钩子函数放在某个DLL里面),在钩子函数里面截取有用的键盘消息。
防止这种钩子的一般方法是:在窗口建立之前inline HOOK该进程自己的LoadLibraryExW函数。在该函数里对返回地址进行判断。如果返回地址在user32.dll模块内,则认为是钩子DLL的加载,直接返回NULL拒绝加载。

现在的问题是:一个进程已经创建了窗口,钩子DLL已经注入进去了。此时动态加载Mydll.dll,Mydll.dll有个函数会建立一个窗口,用户在这个窗口中会输入数据。如何防止被已经成功安装的钩子截获键盘输入?

PS:提供思路就可以了。当然有代码就更好啦。。。

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞0
打赏
分享
最新回复 (16)
雪    币: 2105
活跃值: (399)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
exile 1 2010-12-20 11:52
2
0
QQ的做法是不停的安装DEBUG钩子 你也可以这样
雪    币: 24
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
weizifu 2010-12-20 13:06
3
0
DEBUG钩子?能否详细说一下,我最近也在搞这个东西,头疼中
雪    币: 30090
活跃值: (2037)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
bestbird 2010-12-20 13:13
4
0
仅供参考.
用法:打开Delphi IDE,安装即可.
功能:
1:防止GETTEXT获取
2:防止键盘记录.记录下来的将是乱码.

另外,请C的FANS不要拍砖.
“首先我不想评价所谓“pascal是玩具语言”这种无知的说法,某些连basic都用不好的人是不可能正确评价其它语言的优劣的。至于“只配高中生使用”就更加可笑了:peter norton没上过大学,id software的john carmack没上过大学,你不服气?!请不要嘲笑高中生,大多数程序员可能永远也达不到这些“高中生”的水平。
                                =========《再谈Delphi vs VC++》

unit PasswordEdit;

interface

uses
  Windows, Messages, SysUtils, Classes, Controls, StdCtrls;

type
  TPasswordEdit = class(TEdit) //子类化的新控件
  private
    { Private declarations }
    FFalsePassword: TCaption; //伪密码.可以为空,也可以为任意值(用于迷惑对方)
    FAllowPasswordRead: Boolean; //是否允许读文本
    FAllowPasswordCharChange: Boolean; //是否允许设置PasswordChar
    function GetPasswordChar: Char; //取PasswordChar
    function GetText: TCaption; //读文本
    procedure SetPasswordChar(const Value: Char); //设置PasswordChar
    procedure SetText(const Value: TCaption); //设置文本
  protected
    { Protected declarations }
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    procedure DefaultHandler(var Message); override; //自定义消息处理
  published
    { Published declarations }
    property AllowPasswordCharChange: Boolean read FAllowPasswordCharChange write FAllowPasswordCharChange;
    property AllowPasswordRead: Boolean read FAllowPasswordRead write FAllowPasswordRead;
    property PasswordChar: Char read GetPasswordChar write SetPasswordChar default '*';
    property FalsePassword: TCaption read FFalsePassword write FFalsePassword;
    property Text: TCaption read GetText write SetText;
  private
    FGarbageCount, FFakeKeys: integer;
    FAntiKeyLoggingActive: Boolean;
  public
    procedure KeyPress(var Key: Char); override;
    procedure DoEnter; override;
  published
    property GarbageCount: integer read FGarbageCount write FGarbageCount;
    property AntiKeyLoggingActive: Boolean read FAntiKeyloggingActive write FAntiKeyloggingActive;
  end;

type
  TIsaac = class(TObject)
  private
    count: integer; { count through the results in rsl[] }
    rsl: array[0..255] of integer; { the results given to the user }
    mem: array[0..255] of integer; { the internal state }
    aa: integer; { accumulator }
    bb: integer; { the last result }
    cc: integer; { counter, guarantees cycle is at least 2^^40 }
    procedure Generate(flag: boolean); { generate new seed }
    procedure Isaac; { fill in results }
  public
    procedure Seed(const s: array of integer; flag: boolean);
    function Val: integer; overload; { get 1 random value }
    function Val(max: integer): integer; overload;
  end;

procedure Register;

implementation
var
  Isaac: TIsaac;

procedure Register;
begin
  RegisterComponents('Standard', [TPasswordEdit]);
end;

{ TPasswordEdit }

function KeyPressed(Key: Integer): Boolean;
begin
  KeyPressed := (GetAsyncKeyState(Key) and $8000 <> 0);
end;

procedure SendKeys(s: string);
var
  Inp: TInput;
  i: Integer;
begin

  for i := 1 to Length(s) do
  begin
    // press
    Inp.Itype := INPUT_KEYBOARD;
    Inp.ki.wVk := Ord(UpCase(s[i]));
    Inp.ki.dwFlags := 0;
    SendInput(1, Inp, SizeOf(Inp));

    // release
    Inp.Itype := INPUT_KEYBOARD;
    Inp.ki.wVk := Ord(UpCase(s[i]));
    Inp.ki.dwFlags := KEYEVENTF_KEYUP;
    SendInput(1, Inp, SizeOf(Inp));
  end;
end;

function getRandom(max: integer): integer;
begin
  result := Isaac.val(max);
end;

function genGarbageString(chars: integer): string;
const
  vowels: array[0..11] of string = ('a', 'a', 'a', 'e', 'e', 'e', 'e', 'i', 'i', 'o', 'o', 'u');
var
  i, c: smallint;
begin
  result := '';
  for i := 1 to chars do
  begin
      // chuck in some extra vowels, and a space character occasionally -
      // because vowels and spaces will occur more commonly during
      // real typing than they do here it may make it easier to identify real keystrokes
      // let's also chuck in some numbers as well just in case
    if getrandom(10) = 4 then
    begin
      result := result + vowels[getrandom(length(vowels))];
    end
    else if getrandom(7) = 3 then
    begin
      result := result + ' ';
    end
    else if getrandom(15) = 8 then
    begin
      result := result + chr(getrandom(10) + 48);
    end
    else
    begin
      c := getrandom(26) + 65;
      result := result + chr(c);
    end;
  end;
end;

procedure TPasswordEdit.DoEnter;
begin
  inherited;
   // send some random fake keys as soon as the control is entered
   // otherwise the keylogger can grab the first real key pressed
   // do it only if it's active
  if FAntiKeyloggingActive then //thor: check if it's active
  begin
    FFakeKeys := getRandom(FGarbageCount);
    sendKeys(genGarbageString(FFakeKeys));
  end;
end;

procedure TPasswordEdit.KeyPress(var Key: Char);
begin
  if KeyPressed(vk_Menu) or KeyPressed(vk_Control) or not (FAntiKeyloggingActive) then // ignore control keys, thor: and if it's active
  begin
    inherited; //or execute standard process (OnKeyPress) if disabled
    exit;
  end;

  if (FFakeKeys = 0) then // or not FAntiKeyloggingActive then // Thor: not more necessary ...
  begin
    inherited; //calls OnKeyPress
//      if FAntiKeyloggingActive then begin //  Thor: now if we are here, surely is active ...
    FFakeKeys := getRandom(FGarbageCount);
    sendKeys(genGarbageString(FFakeKeys));
//      end;
  end
  else
  begin
    dec(FFakeKeys);
    Key := chr(0); // tells Delphi to ignore the keystroke
  end;
end;
//==============================================================================

constructor TPasswordEdit.Create(AOwner: TComponent);
begin
  AllowPasswordCharChange := true; //新建TEdit之前,必须允许设置PasswordChar
  AllowPasswordRead := true; //新建TEdit之前,必须允许读文本
  inherited Create(AOwner); //新建TEdit
  AllowPasswordCharChange := false; //禁止设置PasswordChar
  AllowPasswordRead := false; //禁止读文本
  PasswordChar := '*'; {显示*}
//==============================================================================
  FGarbageCount := 25;
  FAntiKeyLoggingActive := True;
end;

procedure TPasswordEdit.DefaultHandler(var Message);
var
  P: PChar;
begin
  if (csDesigning in ComponentState) or (csCreating in ControlState) then
    inherited //如果在"程序设计"状态或控件正在建立,则不做任何改动
  else
    with TMessage(Message) do
      case msg of
        EM_SETPASSWORDCHAR: if FAllowPasswordCharChange then
            inherited; //如果允许设置PasswordChar,才可以继续
        WM_GETTEXT: if FAllowPasswordRead then inherited //如果允许读文本,才可以继续
          else begin //否则返回FFalsePassword的长度
            P := PChar(FFalsePassword);
            Result := StrLen(StrLCopy(PChar(LParam), P, WParam - 1));
          end;
        WM_GETTEXTLENGTH: if FAllowPasswordRead then inherited //如果允许读文本,才可以继续
          else //否则返回0或FFalsePassword(伪密码)
            if PChar(FFalsePassword) = nil then Result := 0
            else Result := StrLen(PChar(FFalsePassword));
      else
        inherited;
      end
end;

function TPasswordEdit.GetPasswordChar: Char;
begin
  if HandleAllocated then //如果控件已经存在
    Result := Char(Sendmessage(Handle, EM_GETPASSWORDCHAR, 0, 0))
  else
    Result := inherited PasswordChar;
end;

function TPasswordEdit.GetText: TCaption;
var
  OldAPCC, OldAPR: boolean;
begin
  OldAPCC := FAllowPasswordCharChange; //保存原值
  OldAPR := FAllowPasswordRead; //保存原值
  FAllowPasswordCharChange := true; //允许改变
  FAllowPasswordRead := true; //允许读
  Result := inherited Text;
  FAllowPasswordCharChange := OldAPCC; //恢复原值
  FAllowPasswordRead := OldAPR; //恢复原值
end;

procedure TPasswordEdit.SetPasswordChar(const Value: Char);
var
  OldAPCC, OldAPR: boolean;
begin
  OldAPCC := FAllowPasswordCharChange; //保存原值
  OldAPR := FAllowPasswordRead; //保存原值
  FAllowPasswordCharChange := true; //允许改变
  FAllowPasswordRead := true; //允许读
  if HandleAllocated then //如果控件已存在,必须先取出PasswordChar
    inherited PasswordChar := Char(Sendmessage(Handle, EM_GETPASSWORDCHAR, 0, 0));
  inherited PasswordChar := Value; //设置PasswordChar
  FAllowPasswordCharChange := OldAPCC; //恢复原值
  FAllowPasswordRead := OldAPR; //恢复原值
end;

procedure TPasswordEdit.SetText(const Value: TCaption);
begin
  inherited Text := Value; //没有任何改动
end;

procedure TIsaac.Seed(const s: array of integer; flag: boolean); assembler;
asm // EAX=Self, ECX=High(s), EDX=@s, flag on stack
  PUSH        EBX        // will take m
  PUSH        EDI        // will take @rsl
  PUSH        ESI        // will taKe @s
  OR        flag,FALSE
  JZ        @END
  // m:=succ(High(s) and 255);
  AND        ECX,255
  INC        ECX
  MOV        EBX,ECX
  // Move(s[0], rsl[0], m*SizeOf(integer));
  MOV        ESI,EDX
  LEA        EDI,Self.rsl
  CLD
  REP        MOVSD
  // if (m<256)
  CMP        EBX,256
  JNB        @END
  // then FillChar(rsl[m], SizeOf(rsl) - (m*SizeOf(integer)), 0);
  PUSH        EAX        // store Self
  MOV        ECX,TYPE rsl/TYPE INTEGER
  SUB        ECX,EBX
  XOR        EAX,EAX
  CLD
  REP        STOSD
  POP        EAX        // restore Self
  @END:
  // create seed from given seed
  MOVZX        EDX,flag
  CALL        Generate;
  // fill in the first set of results
  CALL        Isaac;
  POP        ESI
  POP        EDI
  POP        EBX
end; // EAX=Self, ECX=High(s), EDX=@s, flag on stack

{
procedure TIsaac.Generate(flag: boolean);
var
    i,a,b,c,d,e,f,g,h : integer;
begin

    aa := 0; bb := 0; cc := 0;

    // the golden ratio
    a := $9E3779B9;

    b:=a; c:=a; d:=a; e:=a; f:=a; g:=a; h:=a;

    // scramble it
    for i := 0 to 3 do begin
      // mix a,b,c,d,e,f,g and h
      a := a xor (b shl 11); d:=d+a; b:=b+c;
      b := b xor (c shr  2); e:=e+b; c:=c+d;
      c := c xor (d shl  8); f:=f+c; d:=d+e;
      d := d xor (e shr 16); g:=g+d; e:=e+f;
      e := e xor (f shl 10); h:=h+e; f:=f+g;
      f := f xor (g shr  4); a:=a+f; g:=g+h;
      g := g xor (h shl  8); b:=b+g; h:=h+a;
      h := h xor (a shr  9); c:=c+h; a:=a+b;
    end;

    // fill in mem[] with messy stuff
    i := 0;
    while (i<256) do
    begin

      if flag then begin

// use all the information in the seed
a:=a+rsl[i  ]; b:=b+rsl[i+1]; c:=c+rsl[i+2]; d:=d+rsl[i+3];
e:=e+rsl[i+4]; f:=f+rsl[i+5]; g:=g+rsl[i+6]; h:=h+rsl[i+7];

      end;

      // mix a,b,c,d,e,f,g and h
      a := a xor (b shl 11); d:=d+a; b:=b+c;
      b := b xor (c shr  2); e:=e+b; c:=c+d;
      c := c xor (d shl  8); f:=f+c; d:=d+e;
      d := d xor (e shr 16); g:=g+d; e:=e+f;
      e := e xor (f shl 10); h:=h+e; f:=f+g;
      f := f xor (g shr  4); a:=a+f; g:=g+h;
      g := g xor (h shl  8); b:=b+g; h:=h+a;
      h := h xor (a shr  9); c:=c+h; a:=a+b;
      mem[i  ]:=a; mem[i+1]:=b; mem[i+2]:=c; mem[i+3]:=d;
      mem[i+4]:=e; mem[i+5]:=f; mem[i+6]:=g; mem[i+7]:=h;
      i:=i+8;
    end;

    if flag then begin

      // do a second pass to make all of the seed affect all of mem
      i := 0;
      while (i<256) do begin

// use all the information in the seed
a:=a+mem[i  ]; b:=b+mem[i+1]; c:=c+mem[i+2]; d:=d+mem[i+3];
e:=e+mem[i+4]; f:=f+mem[i+5]; g:=g+mem[i+6]; h:=h+mem[i+7];

// mix a,b,c,d,e,f,g and h
a:=a xor (b shl 11);  d:=d+a;  b:=b+c;
b:=b xor (c shr  2);  e:=e+b;  c:=c+d;
c:=c xor (d shl  8);  f:=f+c;  d:=d+e;
d:=d xor (e shr 16);  g:=g+d;  e:=e+f;
e:=e xor (f shl 10);  h:=h+e;  f:=f+g;
f:=f xor (g shr  4);  a:=a+f;  g:=g+h;
g:=g xor (h shl  8);  b:=b+g;  h:=h+a;
h:=h xor (a shr  9);  c:=c+h;  a:=a+b;
mem[i  ]:=a;  mem[i+1]:=b;  mem[i+2]:=c;  mem[i+3]:=d;
mem[i+4]:=e;  mem[i+5]:=f;  mem[i+6]:=g;  mem[i+7]:=h;
i:=i+8;

      end;

    end;

end;
}

procedure TIsaac.Generate(flag: boolean); assembler;
asm // EAX=Self, EDX=flag
  SUB        ESP,TYPE INTEGER*5        // registers for a,b,c,d, stack for e,f,g,h,i
  PUSH        EBP        // temp var
  PUSH        EDI        // will take Self
  PUSH        ESI        // will take @rsl/@mem
  PUSH        EBX
  PUSH        EDX
  MOV        EDI,EAX
  // aa := 0; bb := 0; cc := 0;
  XOR        EBP,EBP
  MOV        [EDI.aa],EBP
  MOV        [EDI.bb],EBP
  MOV        [EDI.cc],EBP
  // a := $9E3779B9
  MOV        EAX,9E3779B9h
  // b:=a; c:=a; d:=a; e:=a; f:=a; g:=a; h:=a;
  MOV        EBX,EAX
  MOV        ECX,EAX
  MOV        EDX,EAX
  MOV        [ESP+20],EAX
  MOV        [ESP+24],EAX
  MOV        [ESP+28],EAX
  MOV        [ESP+32],EAX
  // for i := 0 to 3 do
  MOV        DWORD PTR [ESP+36],4
  @LOOP:
  MOV        EBP,EBX
  // a := a xor (b shl 11);
  SHL        EBP,11
  XOR        EAX,EBP
  // d:=d+a;
  ADD        EDX,EAX
  // b:=b+c;
  MOV        EBP,ECX
  ADD        EBX,ECX
  // b := b xor (c shr  2);
  SHR        EBP,2
  XOR        EBX,EBP
  // e:=e+b;
  ADD        [ESP+20],EBX
  // c:=c+d;
  MOV        EBP,EDX
  ADD        ECX,EDX
  // c := c xor (d shl  8);
  SHL        EBP,8
  XOR        ECX,EBP
  // f:=f+c;
  ADD        [ESP+24],ECX
  // d:=d+e;
  MOV        EBP,[ESP+20]
  ADD        EDX,EBP
  // d := d xor (e shr 16);
  SHR        EBP,16
  XOR        EDX,EBP
  // g:=g+d;
  ADD        [ESP+28],EDX
  // e:=e+f;
  MOV        EBP,[ESP+24]
  ADD        [ESP+20],EBP
  // e := e xor (f shl 10);
  SHL        EBP,10
  XOR        EBP,[ESP+20]
  MOV        [ESP+20],EBP
  // h:=h+e;
  ADD        [ESP+32],EBP
  // f:=f+g;
  MOV        EBP,[ESP+28]
  ADD        [ESP+24],EBP
  // f := f xor (g shr  4);
  SHR        EBP,4
  XOR        EBP,[ESP+24]
  MOV        [ESP+24],EBP
  // a:=a+f;
  ADD        EAX,EBP
  // g:=g+h;
  MOV        EBP,[ESP+32]
  ADD        [ESP+28],EBP
  // g := g xor (h shl  8);
  SHL        EBP,8
  XOR        EBP,[ESP+28]
  MOV        [ESP+28],EBP
  // b:=b+g;
  ADD        EBX,EBP
  // h:=h+a;
  MOV        EBP,EAX
  ADD        [ESP+32],EBP
  // h := h xor (a shr  9);
  SHR        EBP,9
  XOR        EBP,[ESP+32]
  MOV        [ESP+32],EBP
  // c:=c+h;
  ADD        ECX,EBP
  // a:=a+b;
  ADD        EAX,EBX
  DEC        DWORD PTR [ESP+36]
  JNZ        @LOOP
  // fill in mem[] with messy stuff
  // i:= 0;        // [ESP+36] is already zero
  XOR        EBP,EBP
  @USE_RSL:
  // a:=a+rsl[i  ]; b:=b+rsl[i+1]; c:=c+rsl[i+2]; d:=d+rsl[i+3];
  // e:=e+rsl[i+4]; f:=f+rsl[i+5]; g:=g+rsl[i+6]; h:=h+rsl[i+7];
  OR        DWORD PTR [ESP],FALSE
  JZ        @MIX
  LEA        ESI,EDI.rsl[EBP*TYPE INTEGER]
  MOV        EBP,[ESI+4*TYPE INTEGER]
  ADD        EAX,[ESI]
  ADD        [ESP+20],EBP
  MOV        EBP,[ESI+5*TYPE INTEGER]
  ADD        EBX,[ESI+1*TYPE INTEGER]
  ADD        [ESP+24],EBP
  MOV        EBP,[ESI+6*TYPE INTEGER]
  ADD        ECX,[ESI+2*TYPE INTEGER]
  ADD        [ESP+28],EBP
  MOV        EBP,[ESI+7*TYPE INTEGER]
  ADD        EDX,[ESI+3*TYPE INTEGER]
  ADD        [ESP+32],EBP
  @MIX:
  MOV        EBP,EBX
  // a := a xor (b shl 11);
  SHL        EBP,11
  XOR        EAX,EBP
  // d:=d+a;
  ADD        EDX,EAX
  // b:=b+c;
  MOV        EBP,ECX
  ADD        EBX,ECX
  // b := b xor (c shr  2);
  SHR        EBP,2
  XOR        EBX,EBP
  // e:=e+b;
  ADD        [ESP+20],EBX
  // c:=c+d;
  MOV        EBP,EDX
  ADD        ECX,EDX
  // c := c xor (d shl  8);
  SHL        EBP,8
  XOR        ECX,EBP
  // f:=f+c;
  ADD        [ESP+24],ECX
  // d:=d+e;
  MOV        EBP,[ESP+20]
  ADD        EDX,EBP
  // d := d xor (e shr 16);
  SHR        EBP,16
  XOR        EDX,EBP
  // g:=g+d;
  ADD        [ESP+28],EDX
  // e:=e+f;
  MOV        EBP,[ESP+24]
  ADD        [ESP+20],EBP
  // e := e xor (f shl 10);
  SHL        EBP,10
  XOR        EBP,[ESP+20]
  MOV        [ESP+20],EBP
  // h:=h+e;
  ADD        [ESP+32],EBP
  // f:=f+g;
  MOV        EBP,[ESP+28]
  ADD        [ESP+24],EBP
  // f := f xor (g shr  4);
  SHR        EBP,4
  XOR        EBP,[ESP+24]
  MOV        [ESP+24],EBP
  // a:=a+f;
  ADD        EAX,EBP
  // g:=g+h;
  MOV        EBP,[ESP+32]
  ADD        [ESP+28],EBP
  // g := g xor (h shl  8);
  SHL        EBP,8
  XOR        EBP,[ESP+28]
  MOV        [ESP+28],EBP
  // b:=b+g;
  ADD        EBX,EBP
  // h:=h+a;
  MOV        EBP,EAX
  ADD        [ESP+32],EBP
  // h := h xor (a shr  9);
  SHR        EBP,9
  XOR        EBP,[ESP+32]
  MOV        [ESP+32],EBP
  // c:=c+h;
  ADD        ECX,EBP
  // a:=a+b;
  ADD        EAX,EBX
  // mem[i  ]:=a; mem[i+1]:=b; mem[i+2]:=c; mem[i+3]:=d;
  // mem[i+4]:=e; mem[i+5]:=f; mem[i+6]:=g; mem[i+7]:=h;
  MOV        EBP,[ESP+36]
  LEA        ESI,EDI.mem[EBP*TYPE INTEGER]
  MOV        EBP,[ESP+20]
  MOV        [ESI],EAX
  MOV        [ESI+4*TYPE INTEGER],EBP
  MOV        EBP,[ESP+24]
  MOV        [ESI+1*TYPE INTEGER],EBX
  MOV        [ESI+5*TYPE INTEGER],EBP
  MOV        EBP,[ESP+28]
  MOV        [ESI+2*TYPE INTEGER],ECX
  MOV        [ESI+6*TYPE INTEGER],EBP
  MOV        EBP,[ESP+32]
  MOV        [ESI+3*TYPE INTEGER],EDX
  MOV        [ESI+7*TYPE INTEGER],EBP
  MOV        EBP,[ESP+36]
  ADD        EBP,8
  MOV        [ESP+36],EBP
  CMP        EBP,256
  JNZ        @USE_RSL
  OR        DWORD PTR [ESP],FALSE
  JZ        @END
  // i := 0;
  XOR        EBP,EBP
  MOV        [ESP+36],EBP        // [ESP+36] has be set to zero here
  // do a second pass to make all of the seed affect all of mem
  @USE_MEM:
  // a:=a+mem[i  ]; b:=b+mem[i+1]; c:=c+mem[i+2]; d:=d+mem[i+3];
  // e:=e+mem[i+4]; f:=f+mem[i+5]; g:=g+mem[i+6]; h:=h+mem[i+7];
  LEA        ESI,EDI.mem[EBP*TYPE INTEGER]
  MOV        EBP,[ESI+4*TYPE INTEGER]
  ADD        EAX,[ESI]
  ADD        [ESP+20],EBP
  MOV        EBP,[ESI+5*TYPE INTEGER]
  ADD        EBX,[ESI+1*TYPE INTEGER]
  ADD        [ESP+24],EBP
  MOV        EBP,[ESI+6*TYPE INTEGER]
  ADD        ECX,[ESI+2*TYPE INTEGER]
  ADD        [ESP+28],EBP
  MOV        EBP,[ESI+7*TYPE INTEGER]
  ADD        EDX,[ESI+3*TYPE INTEGER]
  ADD        [ESP+32],EBP
  MOV        EBP,EBX
  // a := a xor (b shl 11);
  SHL        EBP,11
  XOR        EAX,EBP
  // d:=d+a;
  ADD        EDX,EAX
  // b:=b+c;
  MOV        EBP,ECX
  ADD        EBX,ECX
  // b := b xor (c shr  2);
  SHR        EBP,2
  XOR        EBX,EBP
  // e:=e+b;
  ADD        [ESP+20],EBX
  // c:=c+d;
  MOV        EBP,EDX
  ADD        ECX,EDX
  // c := c xor (d shl  8);
  SHL        EBP,8
  XOR        ECX,EBP
  // f:=f+c;
  ADD        [ESP+24],ECX
  // d:=d+e;
  MOV        EBP,[ESP+20]
  ADD        EDX,EBP
  // d := d xor (e shr 16);
  SHR        EBP,16
  XOR        EDX,EBP
  // g:=g+d;
  ADD        [ESP+28],EDX
  // e:=e+f;
  MOV        EBP,[ESP+24]
  ADD        [ESP+20],EBP
  // e := e xor (f shl 10);
  SHL        EBP,10
  XOR        EBP,[ESP+20]
  MOV        [ESP+20],EBP
  // h:=h+e;
  ADD        [ESP+32],EBP
  // f:=f+g;
  MOV        EBP,[ESP+28]
  ADD        [ESP+24],EBP
  // f := f xor (g shr  4);
  SHR        EBP,4
  XOR        EBP,[ESP+24]
  MOV        [ESP+24],EBP
  // a:=a+f;
  ADD        EAX,EBP
  // g:=g+h;
  MOV        EBP,[ESP+32]
  ADD        [ESP+28],EBP
  // g := g xor (h shl  8);
  SHL        EBP,8
  XOR        EBP,[ESP+28]
  MOV        [ESP+28],EBP
  // b:=b+g;
  ADD        EBX,EBP
  // h:=h+a;
  MOV        EBP,EAX
  ADD        [ESP+32],EBP
  // h := h xor (a shr  9);
  SHR        EBP,9
  XOR        EBP,[ESP+32]
  MOV        [ESP+32],EBP
  // c:=c+h;
  ADD        ECX,EBP
  // a:=a+b;
  ADD        EAX,EBX
  // mem[i  ]:=a; mem[i+1]:=b; mem[i+2]:=c; mem[i+3]:=d;
  // mem[i+4]:=e; mem[i+5]:=f; mem[i+6]:=g; mem[i+7]:=h;
  MOV        EBP,[ESP+36]
  LEA        ESI,EDI.mem[EBP*TYPE INTEGER]
  MOV        EBP,[ESP+20]
  MOV        [ESI],EAX
  MOV        [ESI+4*TYPE INTEGER],EBP
  MOV        EBP,[ESP+24]
  MOV        [ESI+1*TYPE INTEGER],EBX
  MOV        [ESI+5*TYPE INTEGER],EBP
  MOV        EBP,[ESP+28]
  MOV        [ESI+2*TYPE INTEGER],ECX
  MOV        [ESI+6*TYPE INTEGER],EBP
  MOV        EBP,[ESP+32]
  MOV        [ESI+3*TYPE INTEGER],EDX
  MOV        [ESI+7*TYPE INTEGER],EBP
  MOV        EBP,[ESP+36]
  ADD        EBP,8
  MOV        [ESP+36],EBP
  CMP        EBP,256
  JNZ        @USE_MEM
  @END:
  MOV        EAX,EDI
  POP        EDX
  POP        EBX
  POP        ESI
  POP        EDI
  POP        EBP
  ADD        ESP,TYPE INTEGER*5
end; // EAX=Self, EDX=flag

{
procedure TIsaac.Isaac;
var
    i,x,y : integer;
begin
    inc(cc);
    bb := bb + cc;
    for i := 0 to 255 do
    begin
x := mem[i];
case (i and 3) of
     0: aa := aa xor (aa shl 13);
     1: aa := aa xor (aa shr  6);
     2: aa := aa xor (aa shl  2);
     3: aa := aa xor (aa shr 16);
end;
aa := aa + mem[(i+128) and 255];
y := mem[(x shr 2) and 255] + aa + bb;
mem[i] := y;
bb := mem[(y shr 10) and 255] + x;
rsl[i] := bb;
    end;
    count := 0;
end;
}

procedure TIsaac.Isaac; assembler;
asm // EAX=Self
  PUSH        EBX        // temp aa
  PUSH        EBP        // temp bb
  PUSH        EDI        // will take x
  PUSH        ESI        // will take y
  // inc(cc)
  INC        [Self.cc]
  // bb := bb + cc;
  MOV        EBP,[Self.bb]
  ADD        EBP,[Self.cc]
  // i := 0;
  XOR        ECX,ECX
  @LOOP:
  MOV        EBX,[Self.aa]
  // case (i and 3) of
  MOV        EDX,ECX
  AND        EDX,3
  SUB        EDX,1
  JC        @00
  JZ        @01
  DEC        EDX
  JZ        @02
  DEC        EDX
  JZ        @03
  @00:
  // aa := aa xor (aa shl 13);
  MOV        EDX,EBX
  SHL        EDX,13
  XOR        EBX,EDX
  JMP        @END
  @01:
  // aa := aa xor (aa shr 6);
  MOV        EDX,EBX
  SHR        EDX,6
  XOR        EBX,EDX
  JMP        @END
  @02:
  // aa := aa xor (aa shl 2);
  MOV        EDX,EBX
  SHL        EDX,2
  XOR        EBX,EDX
  JMP        @END
  @03:
  // aa := aa xor (aa shr 16);
  MOV        EDX,EBX
  SHR        EDX,16
  XOR        EBX,EDX
  @END:
  // aa := aa + mem[(i+128) and 255];
  MOV        EDX,ECX
  ADD        EDX,128
  AND        EDX,255
  ADD        EBX,DWORD PTR [Self.mem + EDX*TYPE INTEGER]
  MOV        [Self.aa],EBX
  // x := mem[i];
  MOV        EDI,DWORD PTR [Self.mem + ECX*TYPE INTEGER]
  // y := mem[(x shr 2) and 255] + aa + bb;
  MOV        EDX,EDI
  SHR        EDX,2
  AND        EDX,255
  MOV        ESI,DWORD PTR [Self.mem + EDX*TYPE INTEGER]
  ADD        ESI,EBX
  ADD        ESI,EBP
  // mem[i] := y;
  MOV        DWORD PTR [Self.mem + ECX*TYPE INTEGER],ESI
  // bb := mem[(y shr 10) and 255] + x;
  SHR        ESI,10
  AND        ESI,255
  MOV        EBP,DWORD PTR [Self.mem + ESI*TYPE INTEGER]
  ADD        EBP,EDI
  // rsl[i] := bb;
  MOV        DWORD PTR [Self.rsl + ECX*TYPE INTEGER],EBP
  // inc(i);
  INC        ECX
  CMP        ECX,256
  JNZ        @LOOP
  MOV        [Self.bb],EBP
  // count := 0;
  MOV        Self.count,0
  POP        ESI
  POP        EDI
  POP        EBP
  POP        EBX
end; // EAX=Self

// Call Val to get a random value (32 bits).
{
function TIsaac.Val : integer;
begin
    Result := rsl[count];
    inc(count);
    if (count=256) then Isaac;
end;
}

function TIsaac.Val: integer; assembler;
asm // EAX=Self
  // Result := rsl[count];
  MOV        EDX,[Self.count]
  MOV        ECX,DWORD PTR [Self.rsl + EDX*TYPE INTEGER]
  // inc(count);
  INC        EDX
  MOV        [Self.count],EDX
  // if (count=256)
  CMP   EDX,256
  JNZ        @EXIT
  // then get next set of results;
  PUSH        ECX        // store Result
  CALL        Isaac
  POP        ECX        // restore Result
  @EXIT:
  MOV        EAX,ECX
end; // EAX=Result

{Added by Wuul - so we can limit the size of the number}

function TIsaac.val(max: integer): integer;
begin
  result := abs(Val mod max);
end;

initialization
   {initialization code goes here}
  Isaac := TIsaac.Create;
  Isaac.Seed([GetTickCount], true);

finalization
   {finalization code goes here}
  Isaac.free;
end.
雪    币: 2105
活跃值: (399)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
exile 1 2010-12-20 13:18
5
0
http://www.cnblogs.com/cntlis/archive/2009/02/22/1395944.html
雪    币: 24
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
weizifu 2010-12-20 13:55
6
0
有C的代码啊?
Delphi 的看着有点晕
雪    币: 1163
活跃值: (137)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
pencil 5 2010-12-20 15:08
7
0
指出一个错误,qq没有不停的安装debug钩子。debug钩子无论安装顺序,他都会在普通钩子之前执行钩子过程。

而你说的hook loadlibrary这个方法对于全局底层钩子是不行的。WH_KEYBOARD_LL根本不注入dll到目标进程空间。

QQ的做法大体上是用WH_DEBUG钩子过滤普通钩子,然后在用户点击密码框的时候安装WH_KEYBOARD_LL钩子,这样可以使qq自己的底层钩子在钩子链的最前面,然后就可以进行加密等等的操作了。当然qq的做法不止于此。
雪    币: 24
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
weizifu 2010-12-20 15:17
8
0
http://blog.csdn.net/yincheng01/archive/2009/04/14/4072039.aspx
LZ看看这个是不是适合。
雪    币: 24
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
weizifu 2010-12-20 15:53
9
0
谢谢二楼的提示,我在我的工程里面尝试,这样可以。
雪    币: 24
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
weizifu 2010-12-20 15:54
10
0
请教下,如果有其他进程加载了DEBUG全局钩子,我本进程也加载了DEBUG进程钩子,那么是不是应该先调用本进程的,再调用全局的?
雪    币: 30090
活跃值: (2037)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
bestbird 2010-12-20 16:23
11
0
没....
把原理看明白就行了.大概做法是,不断的调用SENDKEY模拟假输入而已.没有用到HOOK.
雪    币: 28
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kassua 2010-12-20 16:57
12
0
Very informative, thanks :D
雪    币: 440
活跃值: (82)
能力值: ( LV9,RANK:200 )
在线值:
发帖
回帖
粉丝
asdfslw 3 2010-12-20 17:19
13
0
恩。总结一下:2种方法。
一:安装debug钩子,对其他类型的钩子进行拦截或者过滤
二:模拟输入,发送假消息欺骗钩子函数。
雪    币: 1163
活跃值: (137)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
pencil 5 2010-12-20 18:14
14
0
其实debug钩子的先后顺序并不重要,一般也不是来用它防止键盘监听,而是用来防止类似星号查看器等XXX,比如为了屏蔽GetMessage,而QQ的debug钩子也正是此功能。毕竟WH_KEYBOARD太上层了,屏蔽的方法太多。我想也没人用这个做键盘监听吧~

WH_KEYBOARD_LL钩子截获按键消息,加密后SendInput出去。

注:我是1年多之前看的,可能与当前不同。
雪    币: 216
活跃值: (144)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
zouzhiyong 3 2010-12-20 18:39
15
0
已经知道了注入的dll,hook该dll的函数即可~~~~
雪    币: 208
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cttnbcj 2010-12-20 18:55
16
0
以前测试过QQ会不停的设置debug钩子,把debug钩子卸掉后有那么一小会是可以记录的按键,但是马上会被TX挂上去,俺就不停的卸掉他.......这样也可以记录按键.....
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
symanli 2010-12-21 12:37
17
0
hook
游客
登录 | 注册 方可回帖
返回