How to find source data of file in FAT32 by clusters and FAT table? - filesystems

I have some FAT32 structure output:
bytes_per_sector 0x200
sectors_per_cluster 0x8
reserved_sector_count 0x780
FATtable_count 0x2
root_entry_count 0
hidden_sector_count 0x38
total_sectors_32 0xf17fc8
FATtable_size_32 0x3c40
root_cluster 0x2
fat_info 0x1
backup_BS_sector 0x6
Ok, assume to this information, I jump over reserved_sector_count and get the FAT32 table. #1920 - is offset from te begining - 0x780.
fat32Table #1920
cluster0 ffffff8
cluster1 ffffffff
cluster2 fffffff
cluster3 fffffff
Ok, assume to FATtable_size_32 and FATtable_count I jump over and get to the Data Region at the position #16777216 from the begining. This is the 0 cluster, as I understand. Cluster consists of 8 sectors by 512 byte each. First Directory named "F" - is volume. Second "HELLO.TXT" is a file. DirectoryEntry size of 32 byte.
name #16777216 46 [F ]
ext [ ]
attrib 8
NTreserved 0
CrtTimeTenth 0
createtime 0
createdate 0
accessdate 0
clusterhigh 0
modifiedtime 81e3
modifieddate 4ace
clusterlow 0
filesize 0
name #16777216 48 [HELLO ]
ext [TXT]
attrib 20
NTreserved 18
CrtTimeTenth 5c
createtime 82ca
createdate 4ace
accessdate 4ace
clusterhigh 0
modifiedtime 82d4
modifieddate 4ace
clusterlow 3
filesize 24
Next, I want to find data according to "hello.txt" file. I see clusterlow= 0x03. When I jump to next cluster (+4096 byte) and see data of my file.
name #16781312 This is test
But I don't get how does clusterlow help me to find it? What clusters ffffff8, ffffffff, fffffff in FAT32 table? How to find source data according to all this stuff?

#tilz0R, thanks for a link, but I have already read a doc from MS. And more.
I just get that at the DataRegion (after reserved sectors and FAT32 table) we begin with the cluster2, and clusterlow=0x03 means that source data located in the next cluster3 which is +4096 byte lower than cluster2.
It was easier to understand when I add one more file on a disk and see that first file located in the cluster3 and the second - cluster4.

Related

U-boot Script Bad Header CRC

I have a "flashing" script being loaded into a Uboot, on an iMX6, from a host PC via sdp. The script has been run through mkimage, so it has an image header. Here's the mkimage command:
mkimage -A arm -O linux -T script -C none -a 0 -e 0 -n "U-Boot script" -d $files_dir$flash_txt $files_dir$flash_scr
I can parse the header with binwalk:
$ binwalk -B flash.scr
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 uImage header, header size: 64 bytes, header CRC: 0x315E128A, created: 2021-09-13 14:52:46, image size: 2406 bytes, Data Address: 0x0, Entry Point: 0x0, data CRC: 0x7B909BAE, OS: Linux, CPU: ARM, image type: Script file, compression type: none, image name: "U-Boot script"
It fails to execute, with the uboot saying "Bad Header CRC". So, I'm trying to at least force it to work, while on the device, by correcting the CRC on the spot, using the built-in crc32 tool. It still won't work.
Here are uboot commands I'm trying (after the script is already in memory at address 0x10100000):
# display the script bytes
md 0x10100000
# reset the crc
mw 0x10100004 0x0 1
# verify the change
md 0x10100000
# recalc the crc
crc32 0x10100000 64
# write the crc
#mw 0x10100004 <VALUE> 1
# example:
mw 0x10100004 0x3a833d99 1
# run the script
source 0x10100000
When I do this, I still get the dreaded "Bad Header CRC" error!
I've found numerous sources which reveal / indicate which bytes contain the "header CRC". I've seen multiple sources saying that one needs to "reset" the checksum prior to attempting to compute it. This all looks to be valid logic. What am I doing wrong?
Update
The CORRECT uboot input / results
Per help from sawdust
...
Bad header crc
CTRL+C - Operation aborted.
SDP ended
uboot# md 0x10100000
10100000: 56190527 229a2e76 f4f64161 66090000 '..Vv.."aA.....f
10100010: 00000000 00000000 0533a380 00060205 ..........3.....
10100020: 6f422d55 7320746f 70697263 00000074 U-Boot script...
10100030: 00000000 00000000 00000000 00000000 ................
10100040: 5e090000 00000000 20766e65 61666564 ...^....env defa
10100050: 20746c75 2d20662d 65730a61 766e6574 ult -f -a.setenv
10100060: 7a697320 79625f65 685f6574 725f7865 size_byte_hex_r
10100070: 66746f6f 33352073 35453937 65730a41 ootfs 5379E5A.se
10100080: 766e6574 7a697320 6c625f65 5f6b636f tenv size_block_
10100090: 5f786568 746f6f72 32207366 30444239 hex_rootfs 29BD0
101000a0: 7465730a 20766e65 657a6973 7479625f .setenv size_byt
101000b0: 65685f65 62755f78 20746f6f 30433337 e_hex_uboot 73C0
101000c0: 65730a30 766e6574 7a697320 6c625f65 0.setenv size_bl
101000d0: 5f6b636f 5f786568 6f6f6275 39332074 ock_hex_uboot 39
101000e0: 730a0a45 6e657465 6f722076 7366746f E..setenv rootfs
101000f0: 6c5f615f 6c656261 6f722220 7366746f _a_label "rootfs
uboot# mw 0x10100004 0x0 1
uboot# crc32 0x10100000 0x40 0x10100004
crc32 for 10100000 ... 1010003f ==> 94926f83
uboot# md 0x10100000
10100000: 56190527 836f9294 f4f64161 66090000 '..V..o.aA.....f
10100010: 00000000 00000000 0533a380 00060205 ..........3.....
10100020: 6f422d55 7320746f 70697263 00000074 U-Boot script...
10100030: 00000000 00000000 00000000 00000000 ................
10100040: 5e090000 00000000 20766e65 61666564 ...^....env defa
10100050: 20746c75 2d20662d 65730a61 766e6574 ult -f -a.setenv
10100060: 7a697320 79625f65 685f6574 725f7865 size_byte_hex_r
10100070: 66746f6f 33352073 35453937 65730a41 ootfs 5379E5A.se
10100080: 766e6574 7a697320 6c625f65 5f6b636f tenv size_block_
10100090: 5f786568 746f6f72 32207366 30444239 hex_rootfs 29BD0
101000a0: 7465730a 20766e65 657a6973 7479625f .setenv size_byt
101000b0: 65685f65 62755f78 20746f6f 30433337 e_hex_uboot 73C0
101000c0: 65730a30 766e6574 7a697320 6c625f65 0.setenv size_bl
101000d0: 5f6b636f 5f786568 6f6f6275 39332074 ock_hex_uboot 39
101000e0: 730a0a45 6e657465 6f722076 7366746f E..setenv rootfs
101000f0: 6c5f615f 6c656261 6f722220 7366746f _a_label "rootfs
uboot# source 0x10100000
## Executing script at 10100000
... SUCCESS!!!!!
Pre-upload PC Patch
After running mkimage, I fixed the CRC in this way. This could be written in a more elegant fashion I'm sure - but this proved functional at least:
# The mkimage "header CRC" is invalid for some reason, so it needs to be corrected!
$files_dir=files/
$flash_scr=flash.scr
$flash_hdr=flash.hdr
chmod 644 $files_dir$flash_scr
# zero the current crc, and copy the 64 byte header to a separate file
printf '\x00\x00\x00\x00' | dd of=$files_dir$flash_scr bs=1 seek=4 count=4 conv=notrunc
head -c 64 $files_dir$flash_scr > $files_dir$flash_hdr
# calculate the correct crc
crc=$(crc32 $files_dir$flash_hdr)
b1=$(echo $crc | cut -c 1,2)
b2=$(echo $crc | cut -c 3,4)
b3=$(echo $crc | cut -c 5,6)
b4=$(echo $crc | cut -c 7,8)
# update the script, with the correct value
printf "\x${b1}\x${b2}\x${b3}\x${b4}" | dd of=$files_dir$flash_scr bs=1 seek=4 count=4 conv=notrunc
# clean up
rm $files_dir$flash_hdr
The fundamental flaw in mkimage
Ideally, mkimage would do its job correctly in the first place. Why it is malfunctioning is still a mystery...
What am I doing wrong?
U-Boot almost always assumes hexadecimal values for command arguments, so using the 0x... prefix is actually superfluous. AFAIK there is no way to input decimal values.
# recalc the crc
crc32 0x10100000 64
So when you specify the length of the header in the crc32 command as 64, you have specified an incorrect (header) length of 0x64 or 100 decimal.
Reviewing the U-Boot command response confirms your mistake:
=> crc32 0x10100000 64
CRC32 for 10100000 ... 10100063 ==> 9988c6ca
The address range of 0x10100000 through 0x10100063 is a span of 100 bytes.
Addendum (with revisions)
When you install the calculated value, you are probably introducing an endian (byte order) issue.
# write the crc
#mw 0x10100004 <VALUE> 1
The calculated CRC32 value probably needs to specified in reverse byte-order (assuming little-endian mode for the i.MX6) in the mw command.
For example, the mkimage command installs an original header CRC32 value of d8bc0e3a 3a0ebcd8 in the second word (in little-endian order):
=> md 20000000
20000000: 56190527 3a0ebcd8 a0284161 1f000000 '..V...:aA(.....
20000010: ...
=> imi 20000000
## Checking Image at 20000000 ...
Legacy image found
Image Name: U-Boot script
Image Type: PowerPC Linux Script (uncompressed)
Data Size: ...
After zeroing the second word, the CRC32 command produces the (same) value (as expected) (but as a 4-byte string rather than an integer):
=> crc32 20000000 40
crc32 for 20000000 ... 2000003f ==> d8bc0e3a
If you install this value literally using the mw command, then the byte order is not what is required for a 32-bit word value.
=> mw 20000004 d8bc0e3a
=> md 20000000
20000000: 56190527 d8bc0e3a a0284161 1f000000 '..V:...aA(.....
20000010: ...
=> imi 20000000
## Checking Image at 20000000 ...
Legacy image found
Bad Header Checksum
=>
The mw command treats the value to write as a byte string rather than an integer value an integer value, and therefore does not perform a byte reordering (even though this is a little-endian CPU) a byte reordering of the CRC32 value is required.
Addendum 2
Slight corrections to above in regards to which U-Boot commands are displaying results in little-endian mode.
The md command is displaying word values assuming the stored value is in little-endian mode.
To see the true byte order in memory, use the md.b command.
=> md 20000000 4
20000000: 56190527 3a0ebcd8 a0284161 1f000000 '..V...:aA(.....
=> md.b 20000000 10
20000000: 27 05 19 56 d8 bc 0e 3a 61 41 28 a0 00 00 00 1f '..V...:aA(.....
=>
Therefore, the mkimage command installs an original header CRC32 value of 3a0ebcd8 in the second word (in little-endian order).
The CRC32 command produces the 4-byte value as a byte string (i.e. already in little-endian order).
The mw command is aware that this is a little-endian CPU, and does treats the value to write as an integer value.
Since the CRC32 result is a byte string (rather than an integer value), these bytes must be reordered for input using the mw command.
Got that?
One possible way to avoid this endian confusion would be to use the automatic write feature of the CRC32 command.
Append the address of the header CRC to your crc32 command, and the calculated value will be stored in the correct order for you, e.g.
crc32 0x10100000 0x40 0x10100004
Still wonder why you don't have a good CRC32 in the first place using mkimage, and why you had to resort to this hack.

What is the beginning and the end of this disassembled array?

In a disassembled dll (by IDA), I reached an array, which is commented as an array of int (but it may be of byte):
.rdata:000000018003CC00 ; int boxA[264]
.rdata:000000018003CC00 boxA dd 0 ; DATA XREF: BlockPrepXOR+5FC↑r
.rdata:000000018003CC04 db 0Eh
.rdata:000000018003CC05 db 0Bh
.rdata:000000018003CC06 db 0Dh
.rdata:000000018003CC07 db 9
.rdata:000000018003CC08 db 1Ch
.rdata:000000018003CC09 db 16h
.rdata:000000018003CC0A db 1Ah
.rdata:000000018003CC0B db 12h
.rdata:000000018003CC0C db 12h
.rdata:000000018003CC0D db 1Dh
.rdata:000000018003CC0E db 17h
.rdata:000000018003CC0F db 1Bh
Can I interpret the data as
{000000h, E0B0D09h, 1C161A12h, ..} or
{0, 90D0B0Eh, 121A161Ch, ...} or
{00h,00h,00h,00h, 0Eh, 0Bh, ..} ?
From the comment (from IDA), can you confirm that the array ends at CC00h + 253*4 = D01Fh ? I have another array starting at D020h:
.rdata:000000018003D01D db 0F9h ; ù
.rdata:000000018003D01E db 0A2h ; ¢
.rdata:000000018003D01F db 3Fh ; ?
.rdata:000000018003D020 array4_1248 db 1 ; DATA XREF: BlockPrepXOR+39A↑o
.rdata:000000018003D021 db 2
.rdata:000000018003D022 db 4
.rdata:000000018003D023 db 8
That's just the AES decryption's T8 matrix as described in this paper.
You can easily identify it by looking for the DWORDs values on Google (e.g. this is one of the results).
So that's just data for an AES decryption function.
Note also that the interpretation of a sequence of bytes as a sequence of multi-byte data (WORDs, DWORDs, QWORDs, and so on) depends on the architecture.
For x86, only the little-endian interpretation is correct (this is your case 2) but data may undergo arbitrary manipulations (e.g. it can be bswapped) so, when looking on Google, always use both the little and the big-endian versions of the data.
It's also worth noting that IDA can interpret the bytes as DWORDs (type d twice or use the context menù), showing the correct value based on the architecture of disassembled binary.

Is it possible to determine ENCRYPTBYKEY maximum returned value by the clear text type?

I am going to encrypted several fields in existing table. Basically, the following encryption technique is going to be used:
CREATE MASTER KEY ENCRYPTION
BY PASSWORD = 'sm_long_password#'
GO
CREATE CERTIFICATE CERT_01
WITH SUBJECT = 'CERT_01'
GO
CREATE SYMMETRIC KEY SK_01
WITH ALGORITHM = AES_256 ENCRYPTION
BY CERTIFICATE CERT_01
GO
OPEN SYMMETRIC KEY SK_01 DECRYPTION
BY CERTIFICATE CERT_01
SELECT ENCRYPTBYKEY(KEY_GUID('SK_01'), 'test')
CLOSE SYMMETRIC KEY SK_01
DROP SYMMETRIC KEY SK_01
DROP CERTIFICATE CERT_01
DROP MASTER KEY
The ENCRYPTBYKEY returns varbinary with a maximum size of 8,000 bytes. Knowing the table fields going to be encrypted (for example: nvarchar(128), varchar(31), bigint) how can I define the new varbinary types length?
You can see the full specification here
So lets calculate:
16 byte key UID
_4 bytes header
16 byte IV (for AES, a 16 byte block cipher)
Plus then the size of the encrypted message:
_4 byte magic number
_2 bytes integrity bytes length
_0 bytes integrity bytes (warning: may be wrongly placed in the table)
_2 bytes (plaintext) message length
_m bytes (plaintext) message
CBC padding bytes
The CBC padding bytes should be calculated the following way:
16 - ((m + 4 + 2 + 2) % 16)
as padding is always applied. This will result in a number of padding bytes in the range 1..16. A sneaky shortcut is to just add 16 bytes to the total, but this may mean that you're specifying up to 15 bytes that are never used.
We can shorten this to 36 + 8 + m + 16 - ((m + 8) % 16) or 60 + m - ((m + 8) % 16. Or if you use the little trick specified above and you don't care about the wasted bytes: 76 + m where m is the message input.
Notes:
beware that the first byte in the header contains the version number of the scheme; this answer does not and cannot specify how many bytes will be added or removed if a different internal message format or encryption scheme is used;
using integrity bytes is highly recommended in case you want to protect your DB fields against change (keeping the amount of money in an account confidential is less important than making sure the amount cannot be changed).
The example on the page assumes single byte encoding for text characters.
Based upon some tests in SQL Server 2008, the following formula seems to work. Note that #ClearText is VARCHAR():
52 + (16 * ( ((LEN(#ClearText) + 8)/ 16) ) )
This is roughly compatible with the answer by Maarten Bodewes, except that my tests showed the DATALENGTH(myBinary) to always be of the form 52 + (z * 16), where z is an integer.
LEN(myVarCharString) DATALENGTH(encryptedString)
-------------------- -----------------------------------------
0 through 7 usually 52, but occasionally 68 or 84
8 through 23 usually 68, but occasionally 84
24 through 39 usually 84
40 through 50 100
The "myVarCharString" was a table column defined as VARCHAR(50). The table contained 150,000 records. The mention of "occasionally" is an instance of about 1 out of 10,000 records that would get bumped into a higher bucket; very strange. For LEN() of 24 and higher, there were not enough records to get the weird anomaly.
Here is some Perl code that takes a proposed length for "myVarCharString" as input from the terminal and produces an expected size for the EncryptByKey() result. The function "int()" is equivalent to "Math.floor()".
while($len = <>) {
print 52 + ( 16 * int( ($len+8) / 16 ) ),"\n";
}
You might want to use this formula to calculate a size, then add 16 to allow for the anomaly.

out of order write a file python

I have multiple segments saved in an input file. The format is;
Use case 1:
host port start_byte end_byte
127.0.0.1 12345 0 2048
127.0.0.1 12346 0 1024
127.0.0.1 12347 1024 2048
Use case 2:
host port start_byte end_byte
127.0.0.1 12345 0 2048
127.0.0.1 12346 1024 2048
127.0.0.1 12347 0 1024
Here, the first line is for the reference to understand what each line has.
The host is the localhost but ports are different.
Here we have 3 ports. Port #12345 has entire file (say abc.txt). Port #12347 has
the second segment whereas the port #12346 has the first segment.
Now, I want to read file from the end of file towards the start of file(from line 3 to 1).
The code to download each segment and write to a new file is given below.
def downloadSegment(threadName, fileNameTemp, server_addr, server_port, segment_beginaddr, segment_endaddr, fileName, maxSegmentSize,ip_address,peer_server_port, relevant_path):
downloadSegmentStr = "download," + fileName + ","+segment_beginaddr+"," + segment_endaddr
socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket1.connect((server_addr, int(server_port)))
socket1.send(downloadSegmentStr)
lock.acquire()
with open(fileNameTemp, 'ab') as file_to_write:
file_to_write.seek(int(segment_beginaddr),0)
while True:
data = socket1.recv(maxSegmentSize)
#print data
if not data:
break
#print data
file_to_write.write(data)
file_to_write.close()
lock.release();
socket1.close()
When I write the segment in increasing order (Use case 1), then, it works perfectly. But, when I try using the out of order like explained in above Use case 2, it doesn't work.
Any help is appreciated. Thanks.
You missed these parts of the Python Documentation:
open(name[, mode[, buffering]])
… 'a' for appending (which on some Unix systems means that all
writes append to the end of the file regardless of the current seek
position).
file.seek(offset[, whence])
… Note that if the file is opened for appending (mode 'a' or 'a+'),
any seek() operations will be undone at the next write. If the file is
only opened for writing in append mode (mode 'a'), this method is
essentially a no-op…
Thus, mode 'a' is unsuitable for the task. Sadly, stdio's fopen() offers no mode without a that creates a file if it doesn't exist and doesn't truncate it if it exists. So I'd use os.open() like in:
with os.fdopen(os.open(fileNameTemp, os.O_CREAT|os.O_WRONLY), 'wb') as file_to_write:

FindFirstFile and FindNextFile crash my program in assembly. Why?

I am writing a program that looking for files with the extension ".fly". It displays the names of the founded files, but when I try to use FindFirstFile and FindNextFile, my program crashes. I have tried with FindFirstFileA (ANSI Version of the function) , but my code crashes too. Please, give me a example of code if it's possible.
Please, thanks for your answers. Here's my source code written in FASM Assembly
format pe console 4.0
include 'C:\fasm\INCLUDE\WIN32AX.INC'
; Declare a macro to make buffers
macro dup label,lcount
{ forward
label#:
common
repeat lcount
forward
db 0
common
end repeat }
.code
main:
explore_directoy:
invoke FindFirstFile,file_extension, FIND_STRUCT ; find the first *.fly
mov dword [find_handle], eax
find_more_files:
cmp eax, 0
je exit
call show_file
findnextfile:
invoke FindNextFile, dword [find_handle], FIND_STRUCT
jmp find_more_files
show_file:
invoke MessageBox, NULL, addr msg, addr msg_caption, MB_OK ; Easy way of outputing the text
;invoke MessageBox, NULL, addr cFileName, addr msg_caption, MB_OK
ret
exit:
invoke ExitProcess, 0
datazone:
end_msg db 'End of program', 0
msg db 'File founded', 0
msg_caption db 'Assembly program...', 0
file_extension db '*.fly', 0
find_handle dd 0 ; handles/other stuff..
FIND_STRUCT: ; find structure used with searching
dwFileAttributes dd 0
ftCreationTime dd 0,0
ftLastAccessTime dd 0,0
ftLastWriteTime dd 0,0
nFileSizeHigh dd 0
nFileSizeLow dd 0
dwReserved0 dd 0
dwReserved1 dd 0
dup cFileName, 256 ; found file buffer
dup cAlternate, 14
.end main
Your .text section isn't writable. Change
.code
to
section '.text' readable writable executable
Data should go into the .data section, not the .code section. If your assembler supports uninitialized data (all values defined as ?), then it should go into the .data? section (this is the equivalent of a bss (block started by symbol) section used in some other assemblers).

Resources