首页
论坛
课程
招聘
[分享]HOOK API Lib 0.1 For Delphi
2006-12-5 22:33 11043

[分享]HOOK API Lib 0.1 For Delphi

2006-12-5 22:33
11043
周未一个朋友要求用Delphi做了一个东西,用到了API HOOK,于是写了个简单的

SetOnBefore把函数安装到API之前,可在真正的api执行之前先执行我们的函数
SetOnAfter把函数安装到API之后,可在真正的api执行之后再执行我们的函数

代码写得比较急,还有很多地方可以优化,功能上也有些地方可以于改进一下,如:
替换api,能改变api的返回值等。。。以后有时间玩的时候再升级,没时间就算了。。。

如果你有兴趣转成VC的代码请共享一份给我:)

具体代码如下,其中GetOpCodeSize可参考我早期的“aspr中的精彩代码(一)(修正)、(二)

{
  Name: API Hook Lib
  Version: 0.1
  Author: coded by xIkUg/RCT/CCG
  HomePage: http://www.wintoolspro.com, http://debugman.wintoolspro.com
  CreateDate: 2006-12-03
}

unit uHookLib;

interface
uses
  Windows, SysUtils;

type
  PBytes = ^Byte;
  TMaskTable = array [0..517] of LongWord;

var
  MaskTable: TMaskTable = (
    $00004000, $00004000, $00004000, $00004000,
    $00008000, $00008000, $00000000, $00000000,
    $00004000, $00004000, $00004000, $00004000,
    $00008000, $00008000, $00000000, $00000000,
    $00004000, $00004000, $00004000, $00004000,
    $00008000, $00008000, $00000000, $00000000,
    $00004000, $00004000, $00004000, $00004000,
    $00008000, $00008000, $00000000, $00000000,
    $00004000, $00004000, $00004000, $00004000,
    $00008000, $00008000, $00000008, $00000000,
    $00004000, $00004000, $00004000, $00004000,
    $00008000, $00008000, $00000008, $00000000,
    $00004000, $00004000, $00004000, $00004000,
    $00008000, $00008000, $00000008, $00000000,
    $00004000, $00004000, $00004000, $00004000,
    $00008000, $00008000, $00000008, $00000000,
    $00000000, $00000000, $00000000, $00000000,
    $00000000, $00000000, $00000000, $00000000,
    $00000000, $00000000, $00000000, $00000000,
    $00000000, $00000000, $00000000, $00000000,
    $00000000, $00000000, $00000000, $00000000,
    $00000000, $00000000, $00000000, $00000000,
    $00000000, $00000000, $00000000, $00000000,
    $00000000, $00000000, $00000000, $00000000,
    $00000000, $00000000, $00004000, $00004000,
    $00000008, $00000008, $00001008, $00000018,
    $00002000, $00006000, $00000100, $00004100,
    $00000000, $00000000, $00000000, $00000000,
    $00000100, $00000100, $00000100, $00000100,
    $00000100, $00000100, $00000100, $00000100,
    $00000100, $00000100, $00000100, $00000100,
    $00000100, $00000100, $00000100, $00000100,
    $00004100, $00006000, $00004100, $00004100,
    $00004000, $00004000, $00004000, $00004000,
    $00004000, $00004000, $00004000, $00004000,
    $00004000, $00004000, $00004000, $00004000,
    $00000000, $00000000, $00000000, $00000000,
    $00000000, $00000000, $00000000, $00000000,
    $00000000, $00000000, $00002002, $00000000,
    $00000000, $00000000, $00000000, $00000000,
    $00000020, $00000020, $00000020, $00000020,
    $00000000, $00000000, $00000000, $00000000,
    $00000100, $00002000, $00000000, $00000000,
    $00000000, $00000000, $00000000, $00000000,
    $00000100, $00000100, $00000100, $00000100,
    $00000100, $00000100, $00000100, $00000100,
    $00002000, $00002000, $00002000, $00002000,
    $00002000, $00002000, $00002000, $00002000,
    $00004100, $00004100, $00000200, $00000000,
    $00004000, $00004000, $00004100, $00006000,
    $00000300, $00000000, $00000200, $00000000,
    $00000000, $00000000, $00000000, $00000000,
    $00004000, $00004000, $00004000, $00004000,
    $00000100, $00000100, $00000000, $00000000,
    $00004000, $00004000, $00004000, $00004000,
    $00004000, $00004000, $00004000, $00004000,
    $00000100, $00000100, $00000100, $00000100,
    $00000100, $00000100, $00000100, $00000100,
    $00002000, $00002000, $00002002, $00000100,
    $00000000, $00000000, $00000000, $00000000,
    $00000008, $00000000, $00000008, $00000008,
    $00000000, $00000000, $00000000, $00000000,
    $00000000, $00000000, $00000000, $00000000,
    $00000000, $00000000, $00004000, $00004000,
    $00004000, $00004000, $00004000, $00004000,
    $FFFFFFFF, $FFFFFFFF, $00000000, $FFFFFFFF,
    $00000000, $00000000, $00000000, $00000000,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $00002000, $00002000, $00002000, $00002000,
    $00002000, $00002000, $00002000, $00002000,
    $00002000, $00002000, $00002000, $00002000,
    $00002000, $00002000, $00002000, $00002000,
    $00004000, $00004000, $00004000, $00004000,
    $00004000, $00004000, $00004000, $00004000,
    $00004000, $00004000, $00004000, $00004000,
    $00004000, $00004000, $00004000, $00004000,
    $00000000, $00000000, $00000000, $00004000,
    $00004100, $00004000, $FFFFFFFF, $FFFFFFFF,
    $00000000, $00000000, $00000000, $00004000,
    $00004100, $00004000, $FFFFFFFF, $00004000,
    $00004000, $00004000, $00004000, $00004000,
    $00004000, $00004000, $00004000, $00004000,
    $FFFFFFFF, $FFFFFFFF, $00004100, $00004000,
    $00004000, $00004000, $00004000, $00004000,
    $00004000, $00004000, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $00000000, $00000000, $00000000, $00000000,
    $00000000, $00000000, $00000000, $00000000,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $00000000, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
    $FFFFFFFF, $FFFFFFFF
  );

function SetOnBefore(const DllName: string; const ApiName: string;
  HookProc: Pointer): Boolean;
function SetOnAfter(const DllName: string; const ApiName: string;
  HookProc: Pointer): Boolean;
  
function GetOpCodeSize(Start: Pointer; Tlb: TMaskTable): integer; stdcall;

implementation

var
  JMPGate: array [0..4] of byte = (
    $E9, $00, $00, $00, $00       // JMP XXXXXXXX
  );

  // HookProc offset is 36
  // HookApi offset is  82
  BeforeStub: array [0..93] of byte = (
    $58,                            // 0 pop     eax
    $EB, $08,                       // 1 jmp     short 0040100B
    $00, $00, $00, $00,             // 3 dd      00000000
    $00, $00, $00, $00,             // 7 dd      00000000
    $E8, $00, $00, $00, $00,        // 11 call    00401010
    $59,                            // 16 pop     ecx
    $81, $E9, $10, $10, $40, $00,   // 17 sub     ecx, 00401010
    $89, $A1, $03, $10, $40, $00,   // 23 mov     [ecx+401003], esp
    $89, $81, $07, $10, $40, $00,   // 29 mov     [ecx+401007], eax
    $E8, $36, $01, $00, $00,        // 35 call    HookProc
    $8B, $44, $24, $FC,             // 40 mov     eax, [esp - 4]
    $E8, $00, $00, $00, $00,        // 44 call    0040102D
    $59,                            // 49 pop     ecx
    $89, $44, $24, $FC,             // 50 mov [esp - 4], eax
    $81, $E9, $31, $10, $40, $00,   // 54 sub     ecx, 0040102D
    $8B, $A1, $03, $10, $40, $00,   // 60 mov     esp, [ecx+401003]
    $8B, $81, $07, $10, $40, $00,   // 66 mov     eax, [ecx+401007]
    $50,                            // 72 push    eax
    $90, $90, $90, $90,             // 73
    $90, $90, $90, $90,
    $90, $90, $90, $90,
    $90, $90, $90, $90,   
    $E9, $18, $01, $00, $00         // 89 jmp     HookedApi
  );

  AfterStub: array [0..129] of Byte = (
    $58,                            // 00   pop     eax
    $EB, $0C,                       // 01   jmp     short 0040100F
    $00, $00, $00, $00,             // 03   dd      00000000
    $00, $00, $00, $00,             // 07   add     [eax], al
    $00, $00, $00, $00,             // 0B   add     [eax], al
    $E8, $00, $00, $00, $00,        // 0F   call    00401014
    $59,                            // 14   pop     ecx
    $81, $E9, $14, $10, $40, $00,   // 15   sub     ecx, 00401014
    $89, $A1, $03, $10, $40, $00,   // 1B   mov     [ecx+401003], esp
    $89, $81, $07, $10, $40, $00,   // 21   mov     [ecx+401007], eax
    $8D, $89, $43, $10, $40, $00,   // 27   lea     ecx, [ecx+401043]
    $51,                            // 2D   push    ecx
    $90,                            // 2E   nop
    $90,                            // 2F   nop
    $90,                            // 30   nop
    $90,                            // 31   nop
    $90,                            // 32   nop
    $90,                            // 33   nop
    $90,                            // 34   nop
    $90,                            // 35   nop
    $90,                            // 36   nop
    $90,                            // 37   nop
    $90,                            // 38   nop
    $90,                            // 39   nop
    $90,                            // 3A   nop
    $90,                            // 3B   nop
    $90,                            // 3C   nop
    $90,                            // 3D   nop
    $E9, $57, $01, $00, $00,        // 3E   jmp     0040119A
    $8B, $5C, $24, $FC,             // 43   mov     ebx, [esp-4]
    $E8, $00, $00, $00, $00,        // 47   call    0040104C
    $59,                            // 4C   pop     ecx
    $89, $5C, $24, $FC,             // 4D   mov     [esp-4], ebx
    $81, $E9, $4C, $10, $40, $00,   // 51   sub     ecx, 0040104C
    $89, $81, $0B, $10, $40, $00,   // 57   mov     [ecx+40100B], eax
    $8B, $A1, $03, $10, $40, $00,   // 5D   mov     esp, [ecx+401003]
    $E8, $32, $01, $00, $00,        // 63   call    0040119A
    $E8, $00, $00, $00, $00,        // 68   call    0040106D
    $59,                            // 6D   pop     ecx
    $81, $E9, $6D, $10, $40, $00,   // 6E   sub     ecx, 0040106D
    $8B, $81, $07, $10, $40, $00,   // 74   mov     eax, [ecx+401007]
    $50,                            // 7A   push    eax
    $8B, $81, $0B, $10, $40, $00,   // 7B   mov     eax, [ecx+40100B]
    $C3                             // 81   retn
  );

function GetOpCodeSize(Start: Pointer; Tlb: TMaskTable): integer;
var
  pOPCode: PBytes;
  t, c: LongWord;
  dh, dl, al: byte;
begin
  result := -1;
  t := 0;
  pOPCode := Start;

  repeat
    t := t and $F7;
    c := pOPCode^;
    pOpCode := Pointer((DWORD(pOpCode) + 1));
    t := t or Tlb[c];
  until ((t and $000000FF) and 8) = 0;

  if (c = $0F6) or (c = $0F7) then
  begin
    t := t or $00004000;
    if (pOpCode^ and $38) = 0 then
      t := t or $00008000;
  end
  else if (c = $0CD) then
  begin
    t := t or $00000100;
    if pOpCode^ = $20 then
      t := t or $00000400;
  end
  else if (c = $0F) then
  begin
    al := pOpCode^;
    pOpCode := Pointer((DWORD(pOpCode) + 1));
    t := t or Tlb[al + $100];
    if t = $FFFFFFFF then
      Exit;
  end;

  if (((t and $0000FF00) shr 8) and $80) <> 0 then
  begin
    dh := (t and $0000FF00) shr 8;
    dh := dh xor $20;
    if (c and 1) = 0 then
      dh := dh xor $21;
    t := t and $FFFF00FF;
    t := t or (dh shl 8);
  end;

  if (((t and $0000FF00) shr 8) and $40) <> 0 then
  begin
    al := pOpCode^;
    pOpCode := Pointer((DWORD(pOpCode) + 1));
    c := al;
    c := c or (al shl 8);
    c := c and $C007;
    if (c and $0000FF00) <> $C000 then
    begin
      if ((t and $000000FF) and $10) = 0 then
      begin
        if (c and $000000FF) = 4 then
        begin
          al := pOpCode^;
          pOpCode := Pointer((DWORD(pOpCode) + 1));
          al := al and 7;
          c := c and $0000FF00;
          c := c or al;
        end;
        if (c and $0000FF00) <> $4000 then
        begin
          if (c and $0000FF00) = $8000 then
          begin
            t := t or 4;
          end
          else if c = 5 then
            t := t or 4;
        end
        else
        begin
          t := t or 1;
        end;
      end
      else
      begin
        if (c <> 6) then
        begin
          if (c and $0000FF00) = $4000 then
            t := t or 1
          else if (c and $0000FF00) = $8000 then
            t := t or 2;
        end
        else
          t := t or 2;
      end;
    end;
  end;
  
  if (((t and $000000FF)) and $20) <> 0 then
  begin
    dl := (t and $000000FF);
    dl := dl xor 2;
    t := t and $FFFFFF00;
    t := t or dl;
    if (dl and $10) = 0 then
    begin
      dl := dl xor 6;
      t := t and $FFFFFF00;
      t := t or dl;
    end;
  end;

  if (((t and $0000FF00) shr 8) and $20) <> 0 then
  begin
    dh := (t and $0000FF00) shr 8;
    dh := dh xor 2;
    t := t and $FFFF00FF;
    t := t or (dh shl 8);
    if (dh and $10) = 0 then
    begin
      dh := dh xor 6;
      t := t and $FFFFFF00;
      t := t or dh;
    end;
  end;

  result := DWORD(pOPCode) - DWORD(Start);
  t := t and $707;
  result := result + (t and $000000FF);         //1条指令不可能大过255个字节
  result := result + ((t and $0000FF00) shr 8);
end;

function HookCode(const DllName: string; const ApiName: string;
  HookProc: Pointer): Boolean;
begin
end;

function SetOnBefore(const DllName: string; const ApiName: string;
  HookProc: Pointer): Boolean;
var
  ApiEntry: Pointer;
  DllHandle: THandle;
  ReplaceCodeSize: Integer;
  OpCode: array [0..15] of byte;
  StubPtr: Pointer;
  Addr: LongWord;
  RetSize: LongWord;
  
begin
  Result := False;
  DllHandle := GetModuleHandle(PChar(DllName));
  if DllHandle = 0 then
  begin
    DllHandle := LoadLibrary(PChar(DllName));

    if DllHandle = 0 then Exit;
  end;

  ApiEntry := GetProcAddress(DllHandle, PChar(ApiName));
  if ApiEntry = nil then Exit;

  ReplaceCodeSize := GetOpCodeSize(ApiEntry, MaskTable);

  while ReplaceCodeSize < 5 do
  begin
    ReplaceCodeSize := ReplaceCodeSize +
      GetOpCodeSize(Pointer(LongWord(ApiEntry) + ReplaceCodeSize), MaskTable);
  end;

  if ReplaceCodeSize > 16 then Exit;

  if VirtualProtect(ApiEntry, ReplaceCodeSize, PAGE_READWRITE, nil) then
    Exit;

  CopyMemory(@OpCode, ApiEntry, ReplaceCodeSize);

  StubPtr := VirtualAlloc(nil, SizeOf(BeforeStub), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  if StubPtr = nil then Exit;

  CopyMemory(StubPtr, @BeforeStub, SizeOf(BeforeStub));

  // 求HookProc的地址  
  Addr := LongWord(HookProc) - LongWord(StubPtr) - 35 - 5;
  // 写入HookProc的地址
  PDWORD(LongWord(StubPtr) + 36)^ := Addr;

  // 求HookedApi的地址  
  Addr := LongWord(ApiEntry) + ReplaceCodeSize - LongWord(StubPtr) - 89 - 5;
  // 写入HookedApi的地址
  PDWORD(LongWord(StubPtr) + 90)^ := Addr;

  // 写入被Hook掉的OpCode
  CopyMemory(Pointer(LongWord(StubPtr) + 73), @OpCode, ReplaceCodeSize);

  // 改写Api入口地址
  Addr := LongWord(StubPtr) - LongWord(ApiEntry) - 5;
  PDWORD(LongWord(@JMPGate) + 1)^ := Addr;
  WriteProcessMemory(GetCurrentProcess, ApiEntry, @JMPGate, SizeOf(JMPGate), RetSize);
//  CopyMemory(ApiEntry, @JMPGate, SizeOf(JMPGate));

  Result := True;
end;

function SetOnAfter(const DllName: string; const ApiName: string;
  HookProc: Pointer): Boolean;
var
  ApiEntry: Pointer;
  DllHandle: THandle;
  ReplaceCodeSize: Integer;
  OpCode: array [0..15] of byte;
  StubPtr: Pointer;
  Addr: LongWord;
  RetSize: LongWord;
  
begin
  Result := False;
  DllHandle := GetModuleHandle(PChar(DllName));
  if DllHandle = 0 then
  begin
    DllHandle := LoadLibrary(PChar(DllName));

    if DllHandle = 0 then Exit;
  end;

  ApiEntry := GetProcAddress(DllHandle, PChar(ApiName));
  if ApiEntry = nil then Exit;

  ReplaceCodeSize := GetOpCodeSize(ApiEntry, MaskTable);

  while ReplaceCodeSize < 5 do
  begin
    ReplaceCodeSize := ReplaceCodeSize +
      GetOpCodeSize(Pointer(LongWord(ApiEntry) + ReplaceCodeSize), MaskTable);
  end;

  if ReplaceCodeSize > 16 then Exit;

  if VirtualProtect(ApiEntry, ReplaceCodeSize, PAGE_READWRITE, nil) then
    Exit;

  CopyMemory(@OpCode, ApiEntry, ReplaceCodeSize);

  StubPtr := VirtualAlloc(nil, SizeOf(AfterStub), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  if StubPtr = nil then Exit;

  CopyMemory(StubPtr, @AfterStub, SizeOf(AfterStub));

  // 求HookProc的地址  
  Addr := LongWord(HookProc) - LongWord(StubPtr) - $63 - 5;
  // 写入HookProc的地址
  PDWORD(LongWord(StubPtr) + $64)^ := Addr;

  // 求HookedApi的地址  
  Addr := LongWord(ApiEntry) + ReplaceCodeSize - LongWord(StubPtr) - $3E - 5;
  // 写入HookedApi的地址
  PDWORD(LongWord(StubPtr) + $3F)^ := Addr;

  // 写入被Hook掉的OpCode
  CopyMemory(Pointer(LongWord(StubPtr) + $2E), @OpCode, ReplaceCodeSize);

  // 改写Api入口地址
  Addr := LongWord(StubPtr) - LongWord(ApiEntry) - 5;
  PDWORD(LongWord(@JMPGate) + 1)^ := Addr;
  WriteProcessMemory(GetCurrentProcess, ApiEntry, @JMPGate, SizeOf(JMPGate), RetSize);
//  CopyMemory(ApiEntry, @JMPGate, SizeOf(JMPGate));

  Result := True;
end;

end.

[注意] 欢迎加入看雪团队!base上海,招聘安全工程师、逆向工程师多个坑位等你投递!

收藏
点赞0
打赏
分享
最新回复 (13)
雪    币: 2160
活跃值: 活跃值 (25)
能力值: (RANK:410 )
在线值:
发帖
回帖
粉丝
小虾 活跃值 10 2006-12-5 22:40
2
0
强,先收藏起来再慢慢消化。
雪    币: 243
活跃值: 活跃值 (19)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
firstrose 活跃值 16 2006-12-6 08:14
3
0
原来你也用d啊
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
okhelloman 活跃值 2006-12-8 15:37
4
0
如何使用呢?能否来个调用的例子...
雪    币: 41
活跃值: 活跃值 (187)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
JJGuo 活跃值 2006-12-18 20:51
5
0
对,如何使用?
雪    币: 212
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wping 活跃值 2006-12-19 07:41
6
0
收藏先,我正找它呢
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zhucheba 活跃值 2006-12-20 09:07
7
0
先收藏起来再慢慢消化
雪    币: 204
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
yanjun 活跃值 1 2006-12-20 10:24
8
0
如果我想挂接整个内存空间的莫个API函数,应该如何操作,希望您能够不不吝赐教?
雪    币: 2644
活跃值: 活跃值 (578)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
kagayaki 活跃值 2007-5-26 03:04
9
0
收藏!!!!!!!
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
coffeefrog 活跃值 2007-6-5 10:08
10
0
强。收藏!不过暂时没搞明白怎么用
雪    币: 1294
活跃值: 活跃值 (56)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
yijun8354 活跃值 12 2007-6-5 12:00
11
0
你太强了,收藏学习~~
雪    币: 201
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hexi 活跃值 2007-8-3 14:12
12
0
请看这里:
http://bbs.pediy.com/showthread.php?t=48984
雪    币: 211
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
whllf 活跃值 2007-8-5 10:30
13
0
先收藏!慢慢看
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
help 活跃值 2007-8-9 23:44
14
0
先收藏!慢慢看
游客
登录 | 注册 方可回帖
返回