1.純lua的二進制位操作
lua的二進制文件主要利用string.byte()讀取某個字節,string.char()寫入,示例代碼如下:
function v:xorFile(inputFile,outputFile)
local fileIn,err = io.open(inputFile,"rb")
local content = fileIn:read("*all")
local length = fileIn:seek("end")
fileIn:close()
local fileOut,err = io.open(outputFile,"wb")
fileOut:seek("set",0)
local item
for i=1,length do
item = tonumber(string.byte(content,i))
item = bit:_xor(item,186)
fileOut:write(string.char(item))
end
fileOut:close()
end
這是對整個二進制文件進行異或操作,那麼對某個32位的uint如何操作?比如把第posSrc位的uint32異或posDst位的uint32
function v:XORuint32(inputFile,outputFile,posSrc,posDst)
local fileIn,err = io.open(inputFile,"rb")
local content = fileIn:read("*all")
local length = fileIn:seek("end")
fileIn:seek("set",0)
local dataA = fileIn:read(posSrc-1)
fileIn:seek("set",posSrc+4)
local dataB = fileIn:read("*all")
fileIn:close()
local value1 = tonumber(string.byte(content,posSrc+1))
local value2 = tonumber(string.byte(content,posSrc+2))
local value3 = tonumber(string.byte(content,posSrc+3))
local value4 = tonumber(string.byte(content,posSrc+4))
local key1 = tonumber(string.byte(content,posDst+1))
local key2 = tonumber(string.byte(content,posDst+2))
local key3 = tonumber(string.byte(content,posDst+3))
local key4 = tonumber(string.byte(content,posDst+4))
value1 = bit:_xor(value1,key1)
value2 = bit:_xor(value2,key2)
value3 = bit:_xor(value3,key3)
value1 = bit:_xor(value4,key4)
local fileOut,err = io.open(outputFile,"wb")
fileOut:seek("set",0)
fileOut:write(dataA)
fileOut:write(string.char(value1))
fileOut:write(string.char(value2))
fileOut:write(string.char(value3))
fileOut:write(string.char(value4))
fileOut:write(dataB)
fileOut:close()
end
附上bit的代碼
bit={data32={}}
for i=1,32 do
bit.data32[i]=2^(32-i)
end
function bit:d2b(arg)
local tr={}
for i=1,32 do
if arg >= self.data32[i] then
tr[i]=1
arg=arg-self.data32[i]
else
tr[i]=0
end
end
return tr
end --bit:d2b
function bit:b2d(arg)
local nr=0
for i=1,32 do
if arg[i] ==1 then
nr=nr+2^(32-i)
end
end
return nr
end --bit:b2d
function bit:_xor(a,b)
local op1=self:d2b(a)
local op2=self:d2b(b)
local r={}
for i=1,32 do
if op1[i]==op2[i] then
r[i]=0
else
r[i]=1
end
end
return self:b2d(r)
end --bit:xor
function bit:_and(a,b)
local op1=self:d2b(a)
local op2=self:d2b(b)
local r={}
for i=1,32 do
if op1[i]==1 and op2[i]==1 then
r[i]=1
else
r[i]=0
end
end
return self:b2d(r)
end --bit:_and
function bit:_or(a,b)
local op1=self:d2b(a)
local op2=self:d2b(b)
local r={}
for i=1,32 do
if op1[i]==1 or op2[i]==1 then
r[i]=1
else
r[i]=0
end
end
return self:b2d(r)
end --bit:_or
function bit:_not(a)
local op1=self:d2b(a)
local r={}
for i=1,32 do
if op1[i]==1 then
r[i]=0
else
r[i]=1
end
end
return self:b2d(r)
end --bit:_not
function bit:_rshift(a,n)
local op1=self:d2b(a)
local r=self:d2b(0)
if n < 32 and n > 0 then
for i=1,n do
for i=31,1,-1 do
op1[i+1]=op1[i]
end
op1[1]=0
end
r=op1
end
return self:b2d(r)
end --bit:_rshift
function bit:_lshift(a,n)
local op1=self:d2b(a)
local r=self:d2b(0)
if n < 32 and n > 0 then
for i=1,n do
for i=1,31 do
op1[i]=op1[i+1]
end
op1[32]=0
end
r=op1
end
return self:b2d(r)
end --bit:_lshift
function bit:print(ta)
local sr=""
for i=1,32 do
sr=sr..ta[i]
end
print(sr)
end
以上代碼異或整個文件,1M的文件需要15秒左右,顯然太慢,於是換個腳本,用python試試
2.python的二進制位操作
import binascii
import struct
import sys
def str2hex(str):
hexs = []
for s in str:
tmp = (hex(ord(s)).replace('0x',''))
if len(tmp) == 2:
hexs.append(tmp)
else:
hexs.append('0'+tmp)
return hexs
arr= ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']
arr2 = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
def tran(r):
for i in range(len(arr)):
if r == arr[i]:
return arr2[i]
def packRes(input,output,key):
f = open(input,'rb+')
hexs = []
while True:
t = f.read(1)
if len(t) == 0:
break
hexs.extend(str2hex(t))
f.close()
ff = open(output,'wb')
for i in range(len(hexs)):
a = tran(hexs[i][0])*16+tran(hexs[i][1])
B = struct.pack('B',a^key)
ff.write(B)
ff.close()
def main(p1,p2,p3):
print(p1)
print(p2)
print(p3)
try:
packRes(p1,p2,int(p3))
sys.exit(0)
except:
sys.exit(1)
finally:
pass
if __name__ == "__main__":
if len(sys.argv) >= 1:
p1 = sys.argv[1]
p2 = sys.argv[2]
p3 = sys.argv[3]
main(p1,p2,p3)
同樣的文件要1秒左右,效率提升顯著,然而還是不滿足需求,還是試試C++吧
3.c++的二進制位操作
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cstdlib>
int main(int argc, char* argv[])
{
int i, count, len;
int key;
char buff[1024];
static char tmpfile[] = "~u~0_sw~.f~l";
FILE * in, *out;
if (argc <3)
{
printf("Less Parameter !\n");
printf("Parameter number must at least 2 !!\n");
return 1;
}
len = strlen(argv[2]);
in = fopen(argv[1], "rb");
out = fopen(tmpfile, "wb"); /* creat a temp file */
key = std::atoi(argv[3]);
if (in == NULL)
{
printf("Input File \'%s\' not found !!\n", argv[1]);
exit(1);
}
if (out == NULL)
{
printf("Can not creat temp file \'%s\'\n", tmpfile);
exit(2);
}
while (!feof(in))
{
count = fread(buff, 1, 1024, in);
for (i = 0;i <count;i++)
buff[i] ^= 119;
//buff[i] ^= argv[2][i%len];
fwrite(buff, 1, count, out);
}
fclose(in);
fclose(out);
//printf(argv[1]);
//printf(argv[2]);
if( strcmp(argv[1], argv[2]) == 0)
{
remove(argv[1]);
printf("the key is: %d", key);
}
rename(tmpfile, argv[2]);
return 0;
}
注意再創建控制檯應用程序的設置,不要預編譯頭,否則cpp在MAC下會不兼容。
1M左右,大概需要0.0006秒左右。因爲我們最終是在lua腳本里用,所以接下來說下lua如何調用python
4.lua調用python和C
lua裏面用os.excute來調用本地腳本。
首先看下調用python,由於python是跨平臺的,MAC和WIN10下代碼一致:
os.excute("python xxx.py inputFIle outputFile key")
在win10下調用控制檯程序的話:VS新建控制檯應用程序,調試成功後cd到exe 目錄
os.excute("xxx.exe inputFIle outputFile key")
在mac下先cd到cpp目錄用g++編譯
g++ xxx.cpp
生成a.out
os.excute("./a.out inputFIle outputFile key")
5.小結
有人會喜歡那語言做比較,我認爲語言是看場合的,就像你比較匕首和導彈,沒有太大的意義。主要看武器在誰的手裏,怎麼去使用它。
上面對比來看,貌似python比lua效率高很多,然而,我們本不該在lua裏面執行大體積二進制文件的位操作,Lua作爲C的觸手,應該在C裏面綁定一個方法讓lua調用,這樣lua的效率就是C的效率(當然,要扣除一點調用C的成本)。
lua和python在不同場合有着各自的生命力。