天天看点

VBS创建二进制文件的两种方法

搞了一天,在网上看了很多,发现这种比较少有,高手都不屑来写,所以记录一下,给自己那些有需要的人。

主要是受到文章点击打开链接的启发,基本属于实践和翻译。

不多说,方法一,借用ADODB.Stream,具体实现如下:

'首先定义一些文件打开和写入方式
Const adTypeBinary = 1 '二进制
Const adTypeText = 2   '文本方式
Const adSaveCreateNotExist = 1  '创建保存
Const adSaveCreateOverwrite = 2 '文件本身存在,覆盖保存

'这是一个子过程,判断文件是否存在,并删除
'传入参数: File----待判定的文件路径
Sub DeleteIfExists(File)
    Set fso = CreateObject("Scripting.FileSystemObject") '使用OCX对象辅助
    if (fso.FileExists(File)) Then     '判断文件是否存在
        fso.DeleteFile File, true      '存在就删除
    End if
End Sub

'这是一个子过程,用于创建二进制木马文件
'传入参数: File----存储的二进制文件路径
Sub CreateExeFile(File)
    Set ados = CreateObject("ADODB.Stream") '使用OCX对象辅助
    ados.Type = adTypeText                  '使用方式必须为Text,否则无法直接写构造的二进制数据
    ados.Open                               '打开流
    ados.WriteText ChrB(&h50) & ChrB(&h4B) & ChrB(&h05) & ChrB(&h06) '写入二进制文本,每个字节用ChrB(&hxx)的方式,而连接使用&操作符
    '此处继续写木马的二进制数据,一般情况下,一行不适合写太多,一般写几十个字节。如我们写一个空zip文件
    For i=1 to 18
        ados.WriteText ChrB(&h0)
    Next
    ados.SaveToFile File, adSaveCreateNotExist '存文件
    ados.Close                                 '关闭流

    '因为以ados.Type=2的时候,写出的文件会被在头部多加两个字节。
    '而二进制的方式写文件,传入参数又要为Bytes类型数组,不能为构造的二进制数据。
    ados.Open                  '打开流
    ados.Type = adTypeBinary   '设置二进制方式读写
    ados.LoadFromFile File     '读取文件
    ados.Position = 2          '设置偏移为,跳过前面多加的两个字节
    arrBytes = ados.Read       '变量arrBytes为读取的返回,为Bytes类型的数组
    ados.Position = 0          
    ados.SetEOS                '这两步正确也必要,不过没有懂,感觉应该是设置写入位置为起始,同时结束读取流
    ados.Write arrBytes        '将Bytes的数组写入到流
    ados.SaveToFile File, adSaveCreateOverwrite '将流中数据保存到文件中,以覆盖方式
    ados.Close                 '关闭流
End Sub

Dim wsh
Set wsh = CreateObject("WScript.Shell") '打开一个WSH对象
TempDir = wsh.expandEnvironmentStrings("%TEMP%") '将TempDir赋值为%TEMP%环境变量的展开值
FilePath = TempDir & "\Test.zip"      '设置文件路径为%temp%目录下
DeleteIfExists FilePath               '如果原本存在,删除文件
CreateExeFile FilePath                '创建文件

'如果为exe文件,可以进行下面的操作...
'ExeCmd = Chr(34) & FilePath & Chr(34) '在Run的参数(文件全路径)两端加上引号
'wsh.Run ExeCmd                        '运行exe文件
           

这种方法有一个弊端,会将文件两次写向磁盘,第二种方法没有这个问题,借助Scripting.FileSystemObject,同样以记录一个空的zip文件为例。

strPath = "C:\Zip.zip"

Set objFso = CreateObject("Scripting.FileSystemObject") '使用FileSystemObject
'使用OpenTextFile打开文件得到的对象,第三个参数设置为True,则创建一个新的空文件文件到磁盘
With objFso.OpenTextFile(strPath, 2, True)  
   '接下来循环向新文件写数据,使用一个方法,将十六进制字符串两个两个的取出,并在前面加上&h,然后转换为十进制数字(Clng),之后直接写入。
   For x = 1 To 44 Step 2
      .Write Chr(Clng("&h" & Mid("504B0506000000000000000000000000000000000000",x,2)))
   Next
   .Close '关闭文件
End With  '文件对象使用完毕
           

因为是写小文件,未对效率做过多验证。这两种方法下,大文件测试过方法180多兆,写了大概两分钟时间才写完。方法二未做过验证。