拉取远程代码与本地代码合并_远程登陆报警器及源代码

这个实战小工具是“吃了亏”才反思出来,名字叫“远程登陆报警器”(有点土),设计目的是为了在远程“勘验“嫌疑人的服务器时,临时部署在服务器上,防止嫌疑人突然登陆服务器,而你还在撅着屁股埋头苦干,避免被人抓个现行的防御性工具。

一、序言

    2008年写的,没什么技术含量,主要是思路有点意思。

    始于当年的一个小插曲:“那几天,很无聊地远程登陆到一哥们的服务器上,看看他的机器中可有什么好东西,query user后发现他人不在,觉得胆子大了点,就在我翻箱倒柜忘我时,突然弹出一个窗口,惊了我一头汗,

8875430450db36340787c2e9c11e58bf.png

图-1

    晕啊,光顾着找东西,忘了注意他是什么时候上来的。还好是朋友,要是别的什么可就麻烦了。”

    所以设计这个工具的应用场景就是:当你在远程“勘验”别人服务器时,一要做好防御,怎么才能第一时间发现别人(可能是嫌疑人)上来?想知道你们平时用的什么招?

    二、想法

    想到要有个报警器之类的报警程序就好啦!网上搜索,有一个是用批处理来完成记录远程登陆的日志东西:

    建个TSLog.bat文件,用来记录登录者的IP,内容如下:

time /t >>TSLog.log 

netstat -n -p tcp | find ":3389">>TSLog.log 

start Explorer 

    运行后,会在SLog.log中记录如下: 

22:40 TCP 192.168.12.28:3389 192.168.10.123:4903 ESTABLISHED 

22:54 TCP 192.168.12.28:3389 192.168.12.29:1039 ESTABLISHED

    为了让这个批处理在用户登陆时自动执行,这样设置:在终端服务中,我们覆盖用户的登录脚本设置并指定TSLog.bat为用户登录时需要打开的脚本,这样每个用户登录后都必须执行这个脚本,因为默认的脚本是Explorer,所以加上启动Explorer的命令start Explorer,如果不加这一行命令,用户是没有办法进入桌面的!

    但这个并不能实时的报警,只是做为一种记录性东西。

    于是有了写一个报警程序的念头,让它自动报警!

     三、原理及思路

        当我们远程登陆到一个服务器上,都可以用query user命令或netstat –an查看3389端口的连接方或任务管理器中看到当前有几个登陆用户。

43536bcebdfb0a41c4e1502867b278ce.png

图-2

8ea2f5296c04d6c3ea2f0f4658218b61.png

图-3

    在图-2中,我们可以看到有两个IP地址连接到218.X.X.131的3389端口上,这说明有两个用户登陆到服务器上,其中一个是我的IP,另一个就是我那哥们的IP。

    我下面要实现的就是这么个原理,思路是:我登陆进来后,运行我的程序(程序简称“报警器”),当再有人通过3389端口登陆上来时,就会向我报警,界面如图-4:

d9b4832d1b614c07153b38efa1a285c9.png

图-4

    看到这样的,就要收拾工具,擦除痕迹,赶紧闪人啦!

先来看下程序界面,

5cc023377fcf5111563734ede725d268.png

图-5

    在程序中,设定了两个要填写的参数,分别是:你远程登陆的IP和服务器远程终端端口号,解释一下,①你远程登陆的IP:自己远程登陆到服务器会有一个IP,我们要将自己的本地IP填写在这里,到时候程序报警时就会将我们自己的远程登陆IP排除在外。②远程端口号:一般都是3389,但也可能会改变,象在这里我的举例图中就改为了18203。

    当这个参数填写正确后,按“开始”就可以自动监测了,如果有其他人通过远程登陆上来,会立即弹出图-1样的窗口向我们报警。

    在程序中,主要是利用一个Timer来不停地查看当前的连接情况(利用netstat)。这是个演示程序,仅将自己的IP设为报警对象(在“你远程登陆的IP”那个框中填入你自己的IP,如图-5中显示的那样,我的IP为220.179.X.X,服务器的端口号为:18203),如果需要将自己设为排除对象(报其他人远程登陆的警),请修改源程序(将“=”修改为“<>”就可以啦),很方便的。

    这里给出正宗的源代码,今天看了下,网上的代码都是流出去的。

     四、程序源代码

    //程序写于2008年,代码有些幼稚及不规范,请见谅

unit main;

interface

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, StdCtrls, ExtCtrls, WinSock;

type

  TMainForm = class(TForm)

    Eip: TEdit;

    lbl1: TLabel;

    lbl2: TLabel;

    EPort: TEdit;

    timer1: TTimer;

    StartButton: TButton;

    StopButton: TButton;

    procedure StartButtonClick(Sender: TObject);

    procedure StopButtonClick(Sender: TObject);

    procedure FormCreate(Sender: TObject);

    procedure timer1Timer(Sender: TObject);

    procedure EipKeyPress(Sender: TObject; var Key: Char);

    procedure EPortKeyPress(Sender: TObject; var Key: Char);

  private

    { Private declarations }

  public

    { Public declarations }

  end;

type

  TAsnOctetString = record

    stream: pByte;

    length: Cardinal;

    dynamic: Boolean;

  end;

  TAsnObjectIdentifier = record

    idLength: Cardinal;

    ids: Pointer;

  end;

  pAsnObjectIdentifier = ^TAsnObjectIdentifier;

  TAsnObjectSyntax = record

    case asnType: Byte of

      0: (number: LongInt);

      1: (unsigned32: Cardinal);

      2: (counter64: Int64);

      3: (AsnString: TAsnOctetString);

      4: (bits: TAsnOctetString);

      5: (AsnObject: TAsnObjectIdentifier);

      7: (sequence: TAsnOctetString);

      8: (address: TAsnOctetString);

      9: (counter: Cardinal);

      10: (gauge: Cardinal);

      11: (ticks: Cardinal);

      12: (arbitrary: TAsnOctetString);

  end;

  TRFC1157VarBind = record

    name: TAsnObjectIdentifier;

    value: TAsnObjectSyntax;

  end;

  pRFC1157VarBind = ^TRFC1157VarBind;

  TRFC1157VarBindList = record

    list: pRFC1157VarBind;

    len: DWord

  end;

  pRFC1157VarBindList = ^TRFC1157VarBindList;

  pTcpInfo = ^TTcpInfo;

  TTcpInfo = record

    prev: pTcpInfo;

    next: pTcpInfo;

    state: Cardinal;

    localip: Cardinal;

    localport: Cardinal;

    remoteip: Cardinal;

    remoteport: Cardinal;

  end;

  TSnmpExtensionInit = function(dwTimeZeroReference: DWord;

    hPollForTrapEvent: PHandle;

    pFirstSupportedRegion: pAsnObjectIdentifier

    ): Boolean; stdcall;

  TSnmpExtensionQuery = function(requestType: Byte;

    variableBindings: pRFC1157VarBindList;

    errorStatus: pLongInt;

    errorIndex: pLongInt

    ): Boolean; stdcall;

type userarray = array of string; //将字符串分隔成数组

const

  HOSTNAMELEN = 256;

  PORTNAMELEN = 256;

  ADDRESSLEN = HOSTNAMELEN + PORTNAMELEN;

  tcpidentifiers: array[0..9] of Cardinal = (1, 3, 6, 1, 2, 1, 6, 13, 1, 1);

  udpidentifiers: array[0..9] of Cardinal = (1, 3, 6, 1, 2, 1, 7, 5, 1, 1);

  TcpState: array[0..11] of PChar =

  ('???', 'CLOSED', 'LISTENING', 'SYN_SENT',

    'SEN_RECEIVED', 'ESTABLISHED', 'FIN_WAIT', 'FIN_WAIT2',

    'CLOSE_WAIT', 'CLOSING', 'LAST_ACK', 'TIME_WAIT');

var

  MainForm: TMainForm;

implementation

{$R *.dfm}

var

  MySnmpExtensionInit: TSnmpExtensionInit;

  MySnmpExtensionQuery: TSnmpExtensionQuery;

  wsaData: TWSAData;

  hTrapEvent: THandle;

  hIdentifier: TAsnObjectIdentifier;

  bindList: TRFC1157VarBindList;

  bindEntry: TRFC1157VarBind;

  TcpInfoTable: TTcpInfo;

  CurrentIndex: Cardinal;

  newEntry, CurrentEntry: pTcpInfo;

  errorStatus, errorIndex: LongInt;

  localaddr, remoteaddr: array[1..ADDRESSLEN] of Char;

  localname, remotename: array[1..HOSTNAMELEN] of Char;

  remoteport, localport: array[1..PORTNAMELEN] of Char;

  remoteip_array: userarray;

  ipaddr, remote_addr, remote_addr1, tcp_status: string;

  //portnum, remote_portnum: Integer;

  s1, s2: PChar;

  port_mark: Boolean;

  dotnumber: Integer;

function GetPortName(Port: Integer; Proto, name: PChar; NameLen: Integer): PChar;

var Srvent: PServEnt;

begin

  if not port_mark then

  begin

    Srvent := GetServByPort(htons(WORD(Port)), Proto);

    if Srvent = nil then StrPLCopy(name, Format('%d', [Port]), NameLen)

    else

      if name <> MainForm.EPort.text then

        StrPLCopy(name, Format('%s', [Srvent^.s_name]), NameLen);

    Result := name;

  end;

end;

function GetIpHostName(Local: Boolean; ipaddr: DWord; name: PChar; NameLen: Integer): PChar;

var HostEnt: PHostEnt;

  nIpAddr: DWord;

begin

  nIpAddr := htonl(ipaddr);

  if ipaddr = 0 then begin

    if not Local then StrPCopy(name, Format('%d.%d.%d.%d', [(nIpAddr shr 24) and $FF,

        (nIpAddr shr 16) and $FF,

          (nIpAddr shr 8) and $FF,

          nIpAddr and $FF]))

    else Gethostname(name, NameLen);

  end else begin

    if (ipaddr = $0100007F) then

      if Local then Gethostname(name, NameLen)

      else StrCopy(name, 'localhost')

    else begin

      HostEnt := GetHostByAddr(@ipaddr, Sizeof(nIpAddr), PF_INET);

      if HostEnt <> nil then StrCopy(name, HostEnt^.h_name)

      else StrPCopy(name, Format('%d.%d.%d.%d', [(nIpAddr shr 24) and $FF,

          (nIpAddr shr 16) and $FF,

            (nIpAddr shr 8) and $FF,

            nIpAddr and $FF]))

    end;

  end;

  Result := name;

end;

function LoadInetMibEntryPoints: Boolean;

var hInetLib: THandle;

begin

  Result := False;

  hInetLib := LoadLibrary('inetmib1.dll');

  if hInetLib = 0 then Exit;

  @MySnmpExtensionInit := GetProcAddress(hInetLib, 'SnmpExtensionInit');

  if @MySnmpExtensionInit = nil then Exit;

  @MySnmpExtensionQuery := GetProcAddress(hInetLib, 'SnmpExtensionQuery');

  if @MySnmpExtensionQuery = nil then Exit;

  Result := True;

end;

//按所给字符将字符串分隔成数组

function split(s: string; dot: Char): userarray;

var

  str: userarray;

  i, j: Integer;

begin

  i := 1;

  j := 0;

  SetLength(str, 255);

  while Pos(dot, s) > 0 do //Pos返回子串在父串中第一次出现的位置.

  begin

    str[j] := copy(s, i, Pos(dot, s) - i);

    i := Pos(dot, s) + 1;

    s[i - 1] := chr(ord(dot) + 1);

    j := j + 1;

  end;

  dotnumber := j;

  str[j] := copy(s, i, strlen(PChar(s)) - i + 1);

  Result := str;

end;

function GetIPDotCount(IPAddress: string): Integer;

//判断IP的分隔数,分隔号为“.”,如:X.X.X.X,简单的判断IP格式是否正确

var

  i, j: Integer;

begin

  j := 0;

  for i := 1 to 3 do

  begin

    if Pos('.', IPAddress) < 1 then

    begin

      Result := j;

      Exit;

    end;

    IPAddress := StringReplace(IPAddress, '.', '', [rfIgnoreCase]);

    j := j + 1;

  end;

  Result := j;

end;

procedure TMainForm.StartButtonClick(Sender: TObject);

begin

  if Eip.text = '' then

  begin

    ShowMessage('输入你远程登陆的IP!');

    Exit;

  end

  else

  begin

    if GetIPDotCount(Trim(Eip.text)) <> 3 then

    begin

      ShowMessage('你输入的IP格式不对!');

      Exit;

    end;

  end;

  if EPort.text = '' then

  begin

    ShowMessage('输入远程登陆的端口号(如:3389)');

    Exit;

  end;

  ipaddr := Eip.text;

  //portnum := StrToInt(EPort.text);

  timer1.enabled := True;

  StartButton.enabled := False;

  StopButton.enabled := True;

end;

procedure TMainForm.StopButtonClick(Sender: TObject);

begin

  timer1.enabled := False;

  StartButton.enabled := True;

  StopButton.enabled := False;

end;

procedure TMainForm.EipKeyPress(Sender: TObject; var Key: Char);

begin

  if Key = #13 then

  begin

    if Eip.text = '' then

    begin

      ShowMessage('输入你远程登陆的IP!');

      Exit;

    end

    else

    begin

      if GetIPDotCount(Trim(Eip.text)) <> 3 then

      begin

        ShowMessage('你输入的IP格式不对!');

        Exit;

      end;

    end;

  end;

end;

procedure TMainForm.EPortKeyPress(Sender: TObject; var Key: Char);

begin

  if Key = #13 then

  begin

    if EPort.text = '' then

    begin

      ShowMessage('输入远程登陆的端口号(如:3389)');

      Exit;

    end;

  end;

end;

procedure TMainForm.FormCreate(Sender: TObject);

begin

  if WSAStartup($0101, wsaData) <> 0 then begin

    ShowMessage('Could not initialize Winsock.');

    Exit;

  end;

  if not LoadInetMibEntryPoints then begin

    ShowMessage('Could not load extension DLL.');

    Exit;

  end;

  if not MySnmpExtensionInit(GetCurrentTime, @hTrapEvent, @hIdentifier) then begin

    ShowMessage('Could not initialize extension DLL.');

    Exit;

  end;

  timer1.enabled := False;

end;

procedure TMainForm.timer1Timer(Sender: TObject);

begin

  bindEntry.name.idLength := $0A;

  bindEntry.name.ids := @(tcpidentifiers[0]);

  bindList.list := @bindEntry;

  bindList.len := 1;

  TcpInfoTable.prev := @TcpInfoTable;

  TcpInfoTable.next := @TcpInfoTable;

  CurrentIndex := 1;

  CurrentEntry := @TcpInfoTable;

  while True do begin

    if not MySnmpExtensionQuery($A1, @bindList, @errorStatus, @errorIndex) then Exit;

    if bindEntry.name.idLength < $0A then break;

    if CurrentIndex <> (pDWord(Integer(bindEntry.name.ids) + 9 * Sizeof(Cardinal)))^ then begin

      CurrentEntry := TcpInfoTable.next;

      CurrentIndex := (pDWord(Integer(bindEntry.name.ids) + 9 * Sizeof(Cardinal)))^;

    end;

    case (pDWord(Integer(bindEntry.name.ids) + 9 * Sizeof(Cardinal)))^ of

      1: begin // Always allocate a new structure

          newEntry := AllocMem(Sizeof(TTcpInfo));

          newEntry^.prev := CurrentEntry;

          newEntry^.next := @TcpInfoTable;

          CurrentEntry^.next := newEntry;

          CurrentEntry := newEntry;

          CurrentEntry^.state := bindEntry.value.number;

        end;

      2: begin

          CurrentEntry^.localip := (pDWord(bindEntry.value.address.stream))^;

          CurrentEntry := CurrentEntry^.next;

        end;

      3: begin

          CurrentEntry^.localport := bindEntry.value.number;

          CurrentEntry := CurrentEntry^.next;

        end;

      4: begin

          CurrentEntry^.remoteip := (pDWord(bindEntry.value.address.stream))^;

          CurrentEntry := CurrentEntry^.next;

        end;

      5: begin

          CurrentEntry^.remoteport := bindEntry.value.number;

          CurrentEntry := CurrentEntry^.next;

        end;

    end;

  end;

  CurrentEntry := TcpInfoTable.next;

  while CurrentEntry <> @TcpInfoTable do

  begin

    s1 := GetIpHostName(True, CurrentEntry^.localip, PChar(@localname[1]), HOSTNAMELEN);

    s2 := GetPortName(CurrentEntry^.localport, 'tcp', PChar(@localport[1]), PORTNAMELEN);

    StrPCopy(@localaddr[1], Format('%s:%s', [s1, s2]));

    s1 := GetIpHostName(False, CurrentEntry^.remoteip, PChar(@remotename[1]), HOSTNAMELEN);

    s2 := GetPortName(CurrentEntry^.remoteport, 'tcp', PChar(@remoteport[1]), PORTNAMELEN);

    if CurrentEntry^.remoteip <> 0 then

    begin

      if StrToInt(EPort.text) = CurrentEntry^.localport then

      begin

        remoteip_array := split(s1, '.');

        //会生成这样的格式:145.123.210.218.kx.cq.china.com,全是反的,所以当大于3个。分隔号时,下面要转换成正常的IP格式

        if dotnumber > 3 then

          s1 := StrPCopy(s1, Format('%s.%s.%s.%s', [PChar(remoteip_array[3]), PChar(remoteip_array[2]), PChar(remoteip_array[1]), PChar(remoteip_array[0])]));

        port_mark := True;

      end;

      StrPCopy(@remoteaddr[1], Format('%s:%s', [s1, s2]))

    end

    else

    begin

      port_mark := False;

      StrPCopy(@remoteaddr[1], Format('%s:0', [GetIpHostName(False, CurrentEntry^.remoteip, PChar(@remotename[1]), HOSTNAMELEN)]));

    end;

    CurrentEntry := CurrentEntry^.next;

    remote_addr := PChar(@remoteaddr[1]);

    tcp_status := TcpState[CurrentEntry^.state];

    remote_addr1 := copy(remote_addr, 1, Pos(':', remote_addr) - 1);

    if port_mark then

    begin

      if remote_addr1 = Eip.text then

      //这里为举例,设置报警的是我自己的远程登陆IP,如果你设为排除自己登陆的IP,那就是别有人登陆进来了,就要注意了,最好擦除痕迹,赶快闪人。

      begin

        StopButton.Click();

        ShowMessage('有人登陆了,快闪!登陆IP:' + remote_addr1 + ':' + copy(remote_addr, Pos(':', remote_addr) + 1, length(remote_addr) - Pos(':', remote_addr)));

        Exit;

      end

      else port_mark := False;

    end;

    //else

     // remote_portnum := StrToInt(Copy(remote_addr, Pos(':', remote_addr) + 1, length(remote_addr) - Pos(':', remote_addr)));

  end;

end;

end.

     这个程序有一定的实用价值,有兴趣的可以继续深入的完善它。另外,为了快速地清除痕迹,可以将清除痕迹的功能做到这个程序里,这样跑起来会快很多。

    毕竟是2008年写的代码,请多多包涵。

53c6aa8610ae5da1eacdd6bf7bd3e584.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值