AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

simple binary file read/write functions
Goto page Previous  1, 2, 3, 4, 5  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
mare



Joined: 01 Aug 2008
Posts: 18

PostPosted: Tue Aug 05, 2008 6:20 pm    Post subject: Reply with quote

Yes, VarSetCapacity was the problem, i solved that.
The only thing that boders me is BinWrite process speed.
On small files works ok but i tried it on 100MB file,
AMD X2 6000+, 2gigs RAM, took about 25 minutes and it wasn't finished.
But this was whole binary crypting, and then i make like this:

Code:

BinReadCry(file,data) ;read only 8 bytes
enc := encrypt(data,pw) ;encrypt those 8

BinRead(file,rest) ;read the rest, offset set to 8

finish = %enc%%rest%

BinWrite(encfile,finish) ; write the encrypted file


Now, is the a way so i can speed this process a little bit, actualy speed up very much.
I was thinking if there is a way not to read the rest of the file, but only inject the encrypted part, something like editing.

Can this script do the job?
PhiLho's Binary file reading and writing
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4078
Location: Pittsburgh

PostPosted: Tue Aug 05, 2008 7:02 pm    Post subject: Reply with quote

For large files you should use the Windows built-in AES encryption. The AHK binary file I/O should be reasonably fast, that is, avoid the conversion to hex, when possible.
Back to top
View user's profile Send private message
mare



Joined: 01 Aug 2008
Posts: 18

PostPosted: Wed Aug 06, 2008 2:04 am    Post subject: Reply with quote

Encryption is not a problem it is done quickly, but after that BinWrite process is slow.
I didn't use conversion to hex, BinRead returns binary right?

All i did was read binary, encrypt, and write binary.
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4078
Location: Pittsburgh

PostPosted: Wed Aug 06, 2008 2:12 am    Post subject: Reply with quote

The functions here handle the data as hex bytes, therefore they are slow for large files.
Back to top
View user's profile Send private message
mare



Joined: 01 Aug 2008
Posts: 18

PostPosted: Wed Aug 06, 2008 2:18 am    Post subject: Reply with quote

So you are saying that i need to convert to binary and then write the file ?

This proccess is very slow:
Code:
file = test.rar

res := BinRead(file,data)

file1 = test1.rar
res := BinWrite(file1,data)


Do i need to do this?
Code:
file = test.rar

res := BinRead(file,data)

Hex2Bin(b,data)

file1 = test1.rar
res := BinWrite(file1,data)
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4078
Location: Pittsburgh

PostPosted: Wed Aug 06, 2008 2:34 am    Post subject: Reply with quote

Above I posted a link for a faster version, which does not use hex: http://www.autohotkey.com/forum/viewtopic.php?t=4604.
Back to top
View user's profile Send private message
mare



Joined: 01 Aug 2008
Posts: 18

PostPosted: Wed Aug 06, 2008 3:45 pm    Post subject: Reply with quote

Ok this is a complete script, modified a little:
Code:
#MaxMem 128

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; THIS IS THE PART I HAVE CHANGED ;;;;;;;;;;;;;
file = test.rar  ; 100mb file ,we want to write bytes
;FileDelete %file%
;IfNotEqual ErrorLevel,0, MsgBox Can't delete file "%file%"`nErrorLevel = "%ErrorLevel%"

Hex2Bin(b,"000102030405060708090a0b0c0d0e0f00")  ;"000102030405060708090a0b0c0d0e0f00" this is hex value that we want to write, but first convert to bin
res := BinWrite(file,b,17) ; 17 ? 17 like write n=17 bytes?
MsgBox ErrorLevel = %ErrorLevel%`nBytes Written = %res%
res := BinRead(file,data)
MsgBox ErrorLevel = %ErrorLevel%`nBytes Read = %res%
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; /// THIS IS THE PART I HAVE CHANGED ;;;;;;;;;;

ExitApp


Bin2Hex(ByRef h, ByRef b, n=0)      ; n bytes binary data -> stream of 2-digit hex
{                                   ; n = 0: all (SetCapacity can be larger than used!)
   format = %A_FormatInteger%       ; save original integer format
   SetFormat Integer, Hex           ; for converting bytes to hex

   m := VarSetCapacity(b)
   If (n < 1 or n > m)
       n := m
   Address := &b
   h =
   Loop %n%
   {
      x := *Address                 ; get byte in hex
      StringTrimLeft x, x, 2        ; remove 0x
      x = 0%x%                      ; pad left
      StringRight x, x, 2           ; 2 hex digits
      h = %h%%x%
      Address++
   }
   SetFormat Integer, %format%      ; restore original format
}

Hex2Bin(ByRef b, h, n=0)            ; n hex digit-pairs -> binary data
{                                   ; n = 0: all. (Only ByRef can handle binaries)
   m := Ceil(StrLen(h)/2)
   If (n < 1 or n > m)
       n := m
   Granted := VarSetCapacity(b, n, 0)
   IfLess Granted,%n%, {
      ErrorLevel = Mem=%Granted%
      Return
   }
   Address := &b
   Loop %n%
   {
      StringLeft  x, h, 2
      StringTrimLeft h, h, 2
      x = 0x%x%
      DllCall("RtlFillMemory", "UInt", Address, "UInt", 1, "UChar", x)
      Address++
   }
}

/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BinWrite ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|  - Open binary file
|  - (Over)Write n bytes (n = 0: all)
|  - From offset (offset < 0: counted from end)
|  - Close file
|  (Binary)data -> file[offset + 0..n-1], rest of file unchanged
|  Return #bytes actually written
*/ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

BinWrite(file, ByRef data, n=0, offset=0)
{
   ; Open file for WRITE (0x40..), OPEN_ALWAYS (4): creates only if it does not exists
   h := DllCall("CreateFile","str",file,"Uint",0x40000000,"Uint",0,"UInt",0,"UInt",4,"Uint",0,"UInt",0)
   IfEqual h,-1, SetEnv, ErrorLevel, -1
   IfNotEqual ErrorLevel,0,Return,0 ; couldn't create the file

   m = 0                            ; seek to offset
   IfLess offset,0, SetEnv,m,2
   r := DllCall("SetFilePointerEx","Uint",h,"Int64",offset,"UInt *",p,"Int",m)
   IfEqual r,0, SetEnv, ErrorLevel, -3
   IfNotEqual ErrorLevel,0, {
      t = %ErrorLevel%              ; save ErrorLevel to be returned
      DllCall("CloseHandle", "Uint", h)
      ErrorLevel = %t%              ; return seek error
      Return 0
   }

   m := VarSetCapacity(data)        ; get the capacity ( >= used length )
   If (n < 1 or n > m)
       n := m
   result := DllCall("WriteFile","UInt",h,"Str",data,"UInt",n,"UInt *",Written,"UInt",0)
   if (!result or Written < n)
       ErrorLevel = -3
   IfNotEqual ErrorLevel,0, SetEnv,t,%ErrorLevel%

   h := DllCall("CloseHandle", "Uint", h)
   IfEqual h,-1, SetEnv, ErrorLevel, -2
   IfNotEqual t,,SetEnv, ErrorLevel, %t%-%ErrorLevel%

   Return Written
}

/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BinRead ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|  - Open binary file
|  - Read n bytes (n = 0: file size)
|  - From offset (offset < 0: counted from end)
|  - Close file
|  (Binary)data (replaced) <- file[offset + 0..n-1]
|  Return #bytes actually read
*/ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

BinRead(file, ByRef data, n=0, offset=0)
{
   h := DllCall("CreateFile","Str",file,"Uint",0x80000000,"Uint",3,"UInt",0,"UInt",3,"Uint",0,"UInt",0)
   IfEqual h,-1, SetEnv, ErrorLevel, -1
   IfNotEqual ErrorLevel,0,Return,0 ; couldn't open the file

   m = 0                            ; seek to offset
   IfLess offset,0, SetEnv,m,2
   r := DllCall("SetFilePointerEx","Uint",h,"Int64",offset,"UInt *",p,"Int",m)
   IfEqual r,0, SetEnv, ErrorLevel, -3
   IfNotEqual ErrorLevel,0, {
      t = %ErrorLevel%              ; save ErrorLevel to be returned
      DllCall("CloseHandle", "Uint", h)
      ErrorLevel = %t%              ; return seek error
      Return 0
   }

   m := DllCall("GetFileSize","UInt",h,"Int64 *",r)
   If (n < 1 or n > m)
       n := m
   Granted := VarSetCapacity(data, n, 0)
   IfLess Granted,%n%, {
      ErrorLevel = Mem=%Granted%
      Return 0
   }

   result := DllCall("ReadFile","UInt",h,"Str",data,"UInt",n,"UInt *",Read,"UInt",0)

   if (!result or Read < n)
       t = -3
   IfNotEqual ErrorLevel,0, SetEnv,t,%ErrorLevel%

   h := DllCall("CloseHandle", "Uint", h)
   IfEqual h,-1, SetEnv, ErrorLevel, -2
   IfNotEqual t,,SetEnv, ErrorLevel, %t%-%ErrorLevel%

   Return Read
}


And one more questin, i dont understand the offset.
If this is binary file 000000000000000 ,and i want to ADD 11 into file, if i want to write at begining offset has to be 0, what if i want to write somewhere in the midle or at the end ? offset has to be greater than 0, this method only add bytes, it not modifies them right?

A lot of "if's" Smile
Thanks again for you help, i know i'm borring. Smile
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4078
Location: Pittsburgh

PostPosted: Wed Aug 06, 2008 4:08 pm    Post subject: Reply with quote

If you want to modify data, first you have to read it, change, and write it back. Btw, search the Forum for more recent Bin2Hex and Hex2Bin functions, these are written 3 years ago. AHK has evolved since, and we can have shorter, much faster conversions now.
Back to top
View user's profile Send private message
mare



Joined: 01 Aug 2008
Posts: 18

PostPosted: Wed Aug 06, 2008 5:29 pm    Post subject: Reply with quote

I think i finaly made it, need more testing but i'll get back with the results.

Thanks again.
Back to top
View user's profile Send private message
mare



Joined: 01 Aug 2008
Posts: 18

PostPosted: Thu Aug 07, 2008 8:33 pm    Post subject: Reply with quote

Laszlo wrote:
You cannot use normal (string) assignments with binary data. It gets truncated at the first NULL byte. Use instead VarSetCapacity and DllCall("RtlMoveMemory"...)


It looks like this is what exactly happening, and i dont know what to do.

I'm not familiar with DllCall but i allready have VarSetCapacity in your script and script for encryption, it is set to 2048.
I tried to change it but nothing happened.
I think the blowfish encryption is problem also, because when i read 8 bytes, blowfish encrypt and make them 24 bytes, and when i write them thats 12 hex i loose 2 bytes.

This method is fast and good, but this problem i can not solve.
Please help.
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4078
Location: Pittsburgh

PostPosted: Thu Aug 07, 2008 10:40 pm    Post subject: Reply with quote

How do you use Blowfish (parameters, dll)?
Back to top
View user's profile Send private message
mare



Joined: 01 Aug 2008
Posts: 18

PostPosted: Fri Aug 08, 2008 1:17 am    Post subject: Reply with quote

dll 8kb file, i also have one 70kb, but i found a script here wich uses 8kb.

I tried your aes script but i coud not set it properly.
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4078
Location: Pittsburgh

PostPosted: Fri Aug 08, 2008 3:04 am    Post subject: Reply with quote

If we don’t know the parameters, we cannot suggest the right call from AHK. A url to the documentation would do...
Back to top
View user's profile Send private message
mare



Joined: 01 Aug 2008
Posts: 18

PostPosted: Fri Aug 08, 2008 9:26 am    Post subject: Reply with quote

Here is the blow fish script:

Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;   Data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;

data = 526172211a0700cf9073

pw = password
;;;;;;;;;;;;;;;;;;;;;;;;;;;;

pw := encpass(pw)
msgbox %pw%

res := encrypt(data,pw)
msgbox %res%

res := decrypt(res,pw)
msgbox %res%



;used to encrypt a password to make it a lot more secure
EncPass(Key)
{
   ;VarSetCapacity(Output, 2048)

   ATrim = %A_AutoTrim%
   AutoTrim, Off

   Ret := DllCall("blowfish.dll\Encpass", "str", "aircdll.dll", "str", "Encpass", "str", Key, "Cdecl")
   StringTrimLeft, Key, Key, 4

   AutoTrim, %ATrim%
   Return Key
}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;   Encryption
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Encrypt(Data,Key)
{
   ;VarSetCapacity(Output, 2048)

   ATrim = %A_AutoTrim%
   AutoTrim, Off

   Output = %Key%%A_Space%%Data%
   Ret := DllCall("blowfish.dll\Encrypt", "str", "aircdll.dll", "str", "Encrypt", "str", Output, "Cdecl")
   StringTrimLeft, Output, Output, 4

   AutoTrim, %ATrim%
   Return Output
}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;   Decryption
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Decrypt(Data,Key)
{
   ;VarSetCapacity(Output, 2048)

   ATrim = %A_AutoTrim%
   AutoTrim, Off

   Output = %Key%%A_Space%%Data%
   Ret := DllCall("blowfish.dll\Decrypt", "str", "aircdll.dll", "str", "Decrypt", "str", Output, "Cdecl")
   StringTrimLeft, Output, Output, 4

   AutoTrim, %ATrim%
   Return Output
}


All i did was, first read data from file, use this and return data to file.
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4078
Location: Pittsburgh

PostPosted: Fri Aug 08, 2008 4:03 pm    Post subject: Reply with quote

In the function definition EncPass(Key) you process the key. If the result is not text, the instruction StringTrimLeft, Key, Key, 4 would truncate the result. Also, returning it and assigning to pw both truncate the result at the first NUL. If the processed key is not pure text, you have to use ByRef parameters (and the AutoTrim directive is superfluous).

It is the same in Encrypt and Decrypt, with the variable Output. If it is binary, don’t use StringTrimLeft, do not return Output, and do not use assignments (res := ...). As I said, if you need a copy of the result, do it explicitly with DllCall("RtlMoveMemory", Uint,destination_address, UInt,source_address, Uint,length_in_bytes). With manipulation of the source_address (+4) and the length_in_bytes value you can have the StringTrimLeft effect.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page Previous  1, 2, 3, 4, 5  Next
Page 3 of 5

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group