I am trying to build a small app using shellbags in the windows registry. I am trying to decode some data which is in the REG_BINARY form and have no idea where to begin.
If you go to:
Computer\HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\Shell\BagMRU\0
You will find a series of values, 0, 1, 2, 3 e.t.c of type REG_BINARY and opening them sometimes shows what seems to be a folder along with a ton of what seems like gibberish.
I also need to understand the binary columns ('Sort' and 'Colinfo') of keys of the form:
Computer\HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\Shell\Bags\1\Shell\{5C4F28B5-F869-4E84-8E60-F11DB97C5CC7}
I tried looking at shellbags python programs on the web but honestly have no idea what they are doing and they seem to be written with python2 in mind, so no dice.
I already wrote a small python program to help, but it is missing a way to get the node slot and I am trying to link any given folder name to a node slot. Here is my program currently.
from winreg import *
from codecs import decode
folder_reg_path = "Software\\Classes\\Local Settings\\Software\\Microsoft\\Windows\Shell\\Bags\\1375\\Shell"
bags_mru_path = "Software\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\Shell\\BagMRU"
def get_sniffed_folder_type(reg_key):
with OpenKey(HKEY_CURRENT_USER, reg_key) as key:
value = QueryValueEx(key, 'SniffedFolderType')
return '%s' % (value[0])
def get_current_nodeid(reg_key):
with OpenKey(HKEY_CURRENT_USER, reg_key, 0, KEY_READ) as key:
#value = QueryValueEx(key, '0')
#return value[0].hex().decode('utf-8')
value = EnumValue(key, 2)
return decode(value[1], 'ascii', 'ignore')
# which clsid should be used? the last one in the list
def get_current_clsid(reg_key):
with OpenKey(HKEY_CURRENT_USER, reg_key) as key:
key_idx = 0
value = None
# keep looping until the last clsid entry is found
while 1:
try:
temp = EnumKey(key, key_idx)
key_idx += 1
value = temp
except:
break
return value
# the size of icons used by the folder
def get_folder_icon_size(reg_key):
with OpenKey(HKEY_CURRENT_USER, reg_key) as key:
value = QueryValueEx(key, 'IconSize')
return '%d pixels' % (value[0])
# the folder view. details, list, tiles e.t.c
def get_logical_view_mode(reg_key):
with OpenKey(HKEY_CURRENT_USER, reg_key) as key:
value = QueryValueEx(key, 'LogicalViewMode')
logical_view_mode_dict = {1 : "Details view", 2 : "Tiles view", 3 : "Icons view", 4 : "List view", 5 : "Content view"}
return logical_view_mode_dict[value[0]]
# folder view is based on view mode. so you can have a logical view mode of icons view with a view mode of large icons for instance
def get_folder_view_mode(reg_key):
with OpenKey(HKEY_CURRENT_USER, reg_key) as key:
value = QueryValueEx(key, 'Mode')
# view_mode 7 is only available on xp. A dead os
view_mode_dict = {1 : "Medium icons", 2 : "Small icons", 3 : "List", 4 : "Details", 5 : "Thumbnail icons", 6 : "Large icons", 8 : "Content"}
return view_mode_dict[value[0]]
# how is the folder being sorted
def get_folder_sort_by(reg_key):
with OpenKey(HKEY_CURRENT_USER, reg_key) as key:
value = QueryValueEx(key, 'Sort')
folder_sort_dict = {"0E000000" : "Date Modified", "10000000" : "Date Accessed", "0F000000" : "Date Created", "0B000000" : "Type", "0C000000" : "Size", "0A000000" : "Name", "02000000" : "Title", "05000000" : "Tags"}
# we get a byte value which we will hexify and get a rather long string
# similar to : 000000000000000000000000000000000100000030f125b7ef471a10a5f102608c9eebac0c000000ffffffff
reg_value = value[0].hex()
# now for this string, we need to get the last 16 strings. then we now get the first 8 out of it. so we will have
folder_sort_dict_key = (reg_value[-16:][:8]).upper()
#return folder_sort_dict[folder_sort_dict_key]
print (reg_value)
return folder_sort_dict_key
# in what order is the folder being sorted. ascending or descending???
def get_folder_sort_by_order(reg_key):
with OpenKey(HKEY_CURRENT_USER, reg_key) as key:
value = QueryValueEx(key, 'Sort')
folder_sort_dict = {"01000000" : "Ascending", "FFFFFFFF" : "Descending"}
# we get a byte value which we will hexify and get a rather long string
# similar to : 000000000000000000000000000000000100000030f125b7ef471a10a5f102608c9eebac0c000000ffffffff
reg_value = value[0].hex()
# now for this string, we need to get the last 16 strings. then we now get the last 8 out of it. so we will have
folder_sort_dict_key = (reg_value[-16:][-8:]).upper()
return folder_sort_dict[folder_sort_dict_key]
# How is the folder being grouped
def get_folder_group_by(reg_key):
with OpenKey(HKEY_CURRENT_USER, reg_key) as key:
value = QueryValueEx(key, 'GroupByKey:PID')
folder_group_dict = {'10' : "Name", '14' : "Date Modified", '4*' : "Type", '12' : "Size", '15' : "Date Created", '5' : "Tags", '2' : "Title", '16' : "Date Accessed", '0' : "No Group Applied"}
return folder_group_dict[str(value[0])]
# Registry is of the form:
# HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\Bags\1375\Shell\{5C4F28B5-F869-4E84-8E60-F11DB97C5CC7}
# where 1375 is a value called the NodeList, and {5C4F28B5-F869-4E84-8E60-F11DB97C5CC7} is a value under Shell chosen based on creation date
print ( 'The suggested folder type is %s' % get_sniffed_folder_type(folder_reg_path) )
# lets start by getting a value similar to {5C4F28B5-F869-4E84-8E60-F11DB97C5CC7} by finding the last child of folder_reg_path
folder_reg_path = folder_reg_path + '\\' + get_current_clsid(folder_reg_path)
print ( get_current_nodeid(bags_mru_path) )
print ( 'The registry path is %s' % (folder_reg_path) )
icon_size = get_folder_icon_size(folder_reg_path)
logical_view_mode = get_logical_view_mode(folder_reg_path)
view_mode = get_folder_view_mode(folder_reg_path)
sorted_by = get_folder_sort_by(folder_reg_path)
sorted_by_order = get_folder_sort_by_order(folder_reg_path)
folder_group_by = get_folder_group_by(folder_reg_path)
print ('The folder icon size is %s' % icon_size)
print('The folder logical view mode is %s' % logical_view_mode)
print('The folder view mode is %s' % view_mode)
print('The folder is sorted by %s in %s order' % (sorted_by, sorted_by_order))
print('The folder is grouped by: %s' % folder_group_by)
Answer in progress. Please be patient...
When Explorer is opened for the first time in a newly-created account, The folder view will be dtermined by the TopView settings of the corresponding FolderType defined in the registry under:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes
Most users are familiar with a subset of these, the templates available on the Customize tab of a folder's Properties dialog:
General Items (Generic)
Documents
Pictures
Music
Videos
Contacts and Downloads templates exist as well, but they are assigned only co their respective system folders using the paths found under:
HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
A complete list of FolderType IDs and their respective names can be generated with the following PowerShell code:
gp (gci HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes).PSPath |
select PSChildName, CanonicalName | sort CanonicalName |
Out-GridView # or Out-File FTList.txt # or Set-Clipboard
PSChildName CanonicalName
----------- -------------
{db2a5d8f-06e6-4007-aba6-af877d526ea6} AccountPictures
{91475fe5-586b-4eba-8d75-d17434b8cdf6} Communications
{503a4e73-1734-441a-8eab-01b3f3861156} Communications.SearchResults
{80213e82-bcfd-4c4f-8817-bb27601267a9} CompressedFolder
...
{5fa96407-7e77-483c-ac93-691d05850de8} Videos
{631958a6-ad0f-4035-a745-28ac066dc6ed} Videos.Library
{292108be-88ab-4f33-9a26-7748e62e37ad} Videos.LibraryFolder
{ea25fbd7-3bf7-409e-b97f-3352240903f4} Videos.SearchResults
Once a folder has been viewed in Explorer, Windows saves the view settings for that individual folder under two registry keys. If the folders are local, the keys are:
HKCU:\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\BagMRU
--- and ---
HKCU:\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\Bags
Network locations and a special bag, the Desktop layout, are here:
HKCU\Software\Microsoft\Windows\Shell\BagMRU
--- and ---
HKCU\Software\Microsoft\Windows\Shell\Bags
The numbered subkeys under Bags each correspond to a folder. Each can save three seperate view states: Shell (Explorer), ComDLg (eg Notepad), and ComDlgLegacy (eg Reg Export). These can each have a GUID-named sub-key corresponding to the ID of the FolderType applied to the folder. That sub-key contains the various properties of the view:
PS C:\> $Bags = 'HKCU:\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\Bags'
PS C:\> (gci $bags -Recurse | ? PSChildName -like "{*}" | select -first 2)[1] | ft -AutoSize
Hive: HKEY_CURRENT_USER\Software\Classes\Local
Settings\Software\Microsoft\Windows\Shell\Bags\1\Shell
Name Property
---- --------
{5C4F28B5-F869-4E84-8E60-F11DB97C5CC7} Rev : 67
FFlags : 1090519041
Vid : {137E7700-3573-11CF-AE69-08002B2E1262}
Mode : 4
LogicalViewMode : 1
IconSize : 16
Sort : {0, 0, 0, 0...}
ColInfo : {0, 0, 0, 0...}
GroupView : 0
GroupByKey:FMTID : {00000000-0000-0000-0000-000000000000}
GroupByKey:PID : 0
GroupByDirection : 1
Value Name Description
---------- -----------
Rev • Seems to be a counter that increments when BagMRU/Bags are deleted or Reset
Folders is executed from the Folder Options dialog
Fflags • The FolderFlags that apply to the folder view.
GroupView A DWORD flag determining whether or not the view is grouped:
• 0x00000000 = No grouping
• 0xffffffff = View grouped by column specified by the GroupByKey pair.
GroupByDirection A DWORD flag determing sort direction of group names:
• 0x00000001 = Ascending
• 0xffffffff = Descending
Vid, Mode, LogicalViewMode, and IconSize are all detremined by the Icon mode:
Name LVM Mode Vid IconSize
---- --- ---- --- --------
Details 1 4 {137E7700-3573-11CF-AE69-08002B2E1262} 16
Tiles 2 8 {65F125E5-7BE1-4810-BA9D-D271C8432CE3} 48
SmIcons 3 1 {089000C0-3573-11CF-AE69-08002B2E1262} 16..31
Icons(M-XL) 3 1 {0057D0E0-3573-11CF-AE69-08002B2E1262} 33..256
List 4 3 {0E1FA5E0-3573-11CF-AE69-08002B2E1262} 16
Content 5 8 {30C2C434-0889-4C8D-985D-A9F71830B0A9} 32
All of the values that specify columns:
ColInfo
GroupBy
Sort
do so using by specifying the corresponding property as an FMTID- PID pair. The easiest way to determine the pair for a given property is to group a folder on that property, close it, and examine the resulting GroupByKey:FMTID and GroupByKey:PID values in the corresponding Bag. Here’s what I’ve got so far:
FMTID PID Name
----- --- ----
{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 0x010f Camera Maker
{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 0x0110 Camera Model
{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 0x829a Exposure Time
{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 0x8822 Expsure Program
{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 0x9003 Date Taken
{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 0x9204 Expsure Bias
{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 0x9209 Flash Mode
{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 0x920a Focal Length
{28636AA6-953D-11D2-B5D6-00C04FD918D0} 0x05 Computer
{56A3372E-CE9C-11D2-9F0E-006097C686F6} 0x02 Contributing Artists
{56A3372E-CE9C-11D2-9F0E-006097C686F6} 0x04 Album
{56A3372E-CE9C-11D2-9F0E-006097C686F6} 0x05 Year
{56A3372E-CE9C-11D2-9F0E-006097C686F6} 0x07 #
{56A3372E-CE9C-11D2-9F0E-006097C686F6} 0x0b Genre
{56A3372E-CE9C-11D2-9F0E-006097C686F6} 0x0d Album Artist
{56A3372E-CE9C-11D2-9F0E-006097C686F6} 0x23 Beats-per-minute
{56A3372E-CE9C-11D2-9F0E-006097C686F6} 0x24 Conductor
{5CBF2787-48CF-4208-B90E-EE5E5D420294} 0x15 Description
{5CBF2787-48CF-4208-B90E-EE5E5D420294} 0x17 DateVisited
{6444048F-4C8B-11D1-8B70-080036B11A03} 0x0d Dimensions
{64440491-4C8B-11D1-8B70-080036B11A03} 0x03 Frame Width
{64440491-4C8B-11D1-8B70-080036B11A03} 0x04 Frame Height
{64440491-4C8B-11D1-8B70-080036B11A03} 0x06 Frame Rate
{64440492-4C8B-11D1-8B70-080036B11A03} 0x04 Bit Rate
{64440492-4C8B-11D1-8B70-080036B11A03} 0x0b Copyright
{64440492-4C8B-11D1-8B70-080036B11A03} 0x13 Composer
{9B174B34-40FF-11D2-A27E-00C04FC30871} 0x04 Owner
{A0E74609-B84D-4F49-B860-462BD9971F98} 0x64 35 mm Focal Length
{B725F130-47EF-101A-A5F1-02608C9EEBAC} 0x02 FolderName
{B725F130-47EF-101A-A5F1-02608C9EEBAC} 0x04 Type
{B725F130-47EF-101A-A5F1-02608C9EEBAC} 0x0a Name
{B725F130-47EF-101A-A5F1-02608C9EEBAC} 0x0c Size
{B725F130-47EF-101A-A5F1-02608C9EEBAC} 0x0d Attributes
{B725F130-47EF-101A-A5F1-02608C9EEBAC} 0x0e DateModified
{B725F130-47EF-101A-A5F1-02608C9EEBAC} 0x0f DateCreated
{B725F130-47EF-101A-A5F1-02608C9EEBAC} 0x10 DateAccessed
{D35F743A-EB2E-47F2-A286-844132CB1427} 0x64 EXIF Version
{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 0x02 Categories
{DABD30ED-0043-4789-A7F8-D013A4736622} 0x64 Folder
{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 0x06 FolderPath
{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 0x02 Title
{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 0x04 Authors
{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 0x05 Tags
{F7DB74B4-4287-4103-AFBA-F1B13DCD75CF} 0x64 Date
In ColInfo & Sort, the pair is in a binary format, the PROPERTYKEY structure:
typedef struct {
GUID fmtid;
DWORD pid;
} PROPERTYKEY;
There is some byte-shuffling in converting a CLSID-style GUID to its binary equivalent. Using Name as an example:
{B725F130-47EF-101A-A5F1-02608C9EEBAC} 0x0a
becomes
[30 f1 25 b7 ef 47 1a 10 a5 f1 02 60 8c 9e eb ac][0a 00 00 00] ( Continuous in registry, grouped for clarity )
I use this PowerShell snippet to convert a binary GUID/CLSID to its more familiar text representaton:
$Bags = 'HKCU:\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\Bags'
$Sample = gci $rp.Bags -Recurse | ? Property -Contains Sort | Select -First 5 | gp
$Sample | ForEach{ '{{{0}}}' -f [GUID][Byte[]]$_.Sort[20..35] }
Output:
{b725f130-47ef-101a-a5f1-02608c9eebac}
{b725f130-47ef-101a-a5f1-02608c9eebac}
{f29f85e0-4ff9-1068-ab91-08002b27b3d9}
{83914d1a-c270-48bf-b00d-1c4e451b0150}
{f7db74b4-4287-4103-afba-f1b13dcd75cf}
The PROPERTYKEY structures is used to build the structures that define ColInfo and Sort. If we set a folder to have a single column, Name, and examine the resulting ColInfo value, we see the following bytes:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \ Constant
fd df df fd 10 00 00 00 00 00 00 00 00 00 00 00 / Header
[01 00 00 00] ← Column Count
[18 00 00 00] ← Byte count per column?
[[[30 f1 25 b7 ef 47 1a 10 a5 f1 02 60 8c 9e eb ac] ← FMTID
[0a 00 00 00] ← PID ] ← PROPERTYKEY
[da 01 00 00] ← Width (Pixels?) ] <- PROPERTYKEY/Width pair
For each column added to the view, the column count is incremented and the approprate PROPERTYKEY/Width pair is added:
[00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
fd df df fd 10 00 00 00 00 00 00 00 00 00 00 00]
[03 00 00 00]
[18 00 00 00]
[[[30 f1 25 b7 ef 47 1a 10 a5 f1 02 60 8c 9e eb ac]
[0d 00 00 00]] ← 'Attributes'
[53 00 00 00]]
[[[30 f1 25 b7 ef 47 1a 10 a5 f1 02 60 8c 9e eb ac]
[0a 00 00 00]] ← 'Name'
[10 01 00 00]]
[[[30 f1 25 b7 ef 47 1a 10 a5 f1 02 60 8c 9e eb ac]
[04 00 00 00]] ← 'Type'
[0a 01 00 00]]
Sort uses the SORTCOLUMN structure:
typedef struct SORTCOLUMN {
PROPERTYKEY propkey;
SORTDIRECTION direction;
} SORTCOLUMN;
The Sort structure consists of:
Header composed of 16 zero-valued bytes
SORTCOLUMN count (DWORD)
One or more SORTCOLUMN structures
Name, ascending:
[00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00] <- Header
[01 00 00 00] <- SORTCOLUMN count
[[[30 f1 25 b7 ef 47 1a 10 a5 f1 02 60 8c 9e eb ac] <- FMTID
[0a 00 00 00] <- PID ] <- PROPERTYKEY
[01 00 00 00] <- Direction ] <- SORTCOLUMN
and Name, descending:
[00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]
[01 00 00 00]
[[[30 f1 25 b7 ef 47 1a 10 a5 f1 02 60 8c 9e eb ac]
[0a 00 00 00]]
[ff ff ff ff] <- Direction ] <- SORTCOLUMN
When secondary, tertiary or quaternary properties are selected via a < Shift >+click on the column header, the corresponding SORTCOLUMN is added to the Sort structure.
Type, descending, then Name, ascending:
(gp 'HKCU:\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\Bags\66\Shell\{7D49D726-3C21-4F05-99AA-FDC2C9474656}\').Sort | Format-Hex
Path:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000010 02 00 00 00 30 F1 25 B7 EF 47 1A 10 A5 F1 02 60 ....0ñ%·ïG..¥ñ.`
00000020 8C 9E EB AC 04 00 00 00 FF FF FF FF 30 F1 25 B7 ë¬........0ñ%·
00000030 EF 47 1A 10 A5 F1 02 60 8C 9E EB AC 0A 00 00 00 ïG..¥ñ.`ë¬....
00000040 01 00 00 00 ....
[00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]
[02 00 00 00] <- Two columns specified
[[[30 f1 25 b7 ef 47 1a 10 a5 f1 02 60 8c 9e eb ac]
[04 00 00 00]] <- 'TYpe'
[ff ff ff ff]]
[[[30 f1 25 b7 ef 47 1a 10 a5 f1 02 60 8c 9e eb ac]
[0a 00 00 00]] <- 'Name'
[01 00 00 00]]
BagMRU
BagMRU and its sub-keys are the tree-structured index that associates a folder's path with its numbered Bag (NodeSlot). BagMRU and its sub-keys mirror the Shell Namespace, with the BagMRU key itself corresponding to the rooted (virtual) Desktop. Each node in BagMRU corresponds to a folder in the Shell namespace. The fact that folders are referenced by their namespace path means one file system folder, say Documents, will have three separate views:
Desktop\This PC\Documents
Shell:UsersFilesFolder\Documents
Desktop\This PC\C:\Users<UserName>\Documents
No folder names are readily apparent when examining BagMRU; the nodes have simple integer names, and there are no string values. Where's the human-readable path?!?!? Why does MS make everything so difficult?!?!?:D
Well,every integer-named node has a corresponding integer-named REG_BINARY value in its parent node. It is this value that identifies its associated sub-key. The key to the mystery? Those binary values are Item IDs (actually the corresponding ITEMID_CHILD type of the ITEMIDLIST structure). So, we can use the ID Lists of a node and its ancestors to construct an IDLIST_ABSOLUTE, the analog to a fully-qualified path:
But it's still just an array of cryptic bytes. To extract meaningful information, we turn to the Windows API, specifically SHGetNameFromIDList. Per the documentation:
"Retrieves the display name of an item identified by its IDList."
Fortunately, PowerShell can incorporate APIs via Add-Type. Unfortunately, if PInvoke.net deosn't have a C# signature/wrapper in its database, discovering a working signature and wrapper can be frustrating. But through studying other signatures and trial-and-error, I hit on one:
$NSPBsource = #"
using System;
using System.Runtime.InteropServices;
using System.Text;
public class IDLTranslator
{
[DllImport("shell32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Error)]
static extern int SHGetNameFromIDList(IntPtr pidl, uint sigdnName, out StringBuilder ppszName);
public string GetFolderName(Byte[] IDL) {
GCHandle pinnedArray = GCHandle.Alloc(IDL, GCHandleType.Pinned);
IntPtr PIDL = pinnedArray.AddrOfPinnedObject();
StringBuilder name = new StringBuilder(2048);
int result = SHGetNameFromIDList(PIDL, 0x0, out name);
pinnedArray.Free();
return name.ToString();
}
}
"# # End $NSPBsource
Add-Type -TypeDefinition $NSPBsource
$NSPB = New-Object IDLTranslator
# Invocation:
# $FolderName = $NSPB.GetFolderName($IDL)
# Where $IDL is a [Byte[]] ItemIDList
This is enough to deccode the IDLs of the folders rooted in the Desktop:
$BagMRU = 'HKCU:\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\BagMRU'
(gp $Bagmru).PsBase.Properties | ? Name -match '\d+' | ForEach{
$NSPB.GetFolderName($_.Value)
} | sort
OUtput: ( specific results will vary :D )
Control Panel
Dustbin
Keith Miller
Libraries
My Posts
One Drive
Quick Access
Sandbox
Search Results in !Archive
Search Results in !Archive
Search Results in AAA Mess
Search Results in AAA Mess
Search Results in CopyTEst
Search Results in CopyTEst
Search Results in Desktop
Search Results in Desktop
Search Results in Documents
Search Results in Folder View Defaults
Search Results in Folder View Defaults
Search Results in iTunes
Search Results in Local Documents
Search Results in Local Downloads
Search Results in Local Downloads
Search Results in Local Music
Search Results in Local Music
Search Results in Local Pictures
Search Results in Local Videos
Search Results in Microsoft.BingWeather_4.36.20503.0_x64__8wekyb3d8bbwe
Search Results in Microsoft.BingWeather_4.36.20503.0_x64__8wekyb3d8bbwe
Search Results in MTV Party to Go, Vol. 3
Search Results in One Drive
Search Results in One Drive
Search Results in Pictures
Search Results in PoweShell Snippets
Search Results in PoweShell Snippets
Search Results in Private
Search Results in Quick Access
Search Results in Sandbox
Search Results in Sandbox
Search Results in Sandbox
Search Results in Sandbox
Search Results in Screenshots
Search Results in Sort music on Artist
Search Results in Sort music on Artist
Search Results in Standalone Programs
Search Results in Standalone Programs
Search Results in Users
Search Results in Users
Search Results in Windows (C:)
Search Results in Windows (C:)
This Device
This Device
This PC
Websites
Nifty, huh? And don't worry, those "Search Results..." lines that appear to be duplicates aren't --- they work together. Because the .SearchResults and .Library FolderTypes have mutilple TopViews (selected via ArrangeBy >) available, one bag specifies which TopView is last used (and hence used when the folder is re-displayed) and the other one(s) hold the view settings for a specific TopView. More on that later --- we're not done with paths yet.
To be continued...
I am using reader ACR1281 and MIFARE cards.
I communicate with the cards using python smartcard library (pc/sc).
I know the MIFARE key to read the card blocks and want to store the key in reader to use it (as I see in the doc this is the only way to use my key - store it in the reader and 'authenticated' with it the block to read).
But specified in the ACR documentation command FF 82 00 00 06 FF FF FF FF FF FF returns error 63 00.
In the command above I use key number 0 (volatile) and key value FF FF FF FF FF FF.
Silly error.
I am using volatile key (P1 = key_structure = 0).
And by the ACS documentation for that I can use only one key number - session key (P2 = key_number = 0x20).
So correct command is
FF 82 00 20 06 FF FF FF FF FF FF
Wrong command I'd got from another ACS reader documentation.
I'm writing python script and I need to obtain exif information from raw photo file (.CR2 for example).
I found Python Rawkit offer the ability to do that.
with Raw(filename=image_path) as raw:
print raw.metadata
Metadata(aperture=-1.2095638073643314e+38, timestamp=4273602232L,
shutter=-1.1962713245823862e+38, flash=True,
focal_length=-1.2228562901462766e+38, height=3753,
iso=-1.182978841800441e+38,
make='Canon', model='EOS 5D Mark II',
orientation=0, width=5634)
But I'm a little bit confused, how read this values ?. For example I'm expecting iso value like 100/200/400 but what is -1.182978841800441e+38 ?
My question is not specific for iso, it's also for shutter, aperture, ...
I ckecked libraw and rawkit doc but was not able to find how read / convert this kind of values.
This part in the doc is not very detailed :
float iso_speed;
ISO sensitivity.
float shutter;
Shutter speed.
Can someone help me understand how to read these values?
Thanks
[Update]
As neo suggest, I will use ExifRead. In fact it's a better choice, I'm writting a python script. With ExifRead no need of extra C library dependency.
I was able to open Canon raw file and parse Exif but unfortunately facing a wrong value for the aperture :
EXIF ApertureValue (Ratio): 3
# My photo was taken in 2.8 (maybe a rounded value on this flag ?)
Quick answer : use Fnumber flag
EXIF FNumber (Ratio): 14/5
14/5 is in fact 2.8 (do the math)
Long answer (how I found / debug that) :
Reading this exelent link Understanding What is stored in a Canon RAW .CR2 file, How and Why ( http://lclevy.free.fr/cr2/ ) I decided to decode myself and know what is going on.
This link send me on the graal to decode a raw file cr2_poster.pdf
From that I thought the best value seems to be in my canon specific MakerNote section on the FNumber value. (All values description is here canon_tags)
Tag Id : 3 (In fact 0x0003 that you write 0x3)
Name : FNumber
I opened my file with an Hexa editor (hexedit) and ... I was totally lost.
Key things :
An offset is a address in the file that will contain your value.
Read : C8 05 in the file should be read 05C8. Example for an offset, the address is 0x5C8
With that found the MakeNote section is easy.
Quick way is to search directly the 0x927c MarkerNote (so in the file 7C 92) flag that contain the address of the MakerNote section.
If you are not able to found that, go throught the IFD section to find the EXIF subsection. And then in that subsection you will find the MakerNote section
Tag Type Count Value
7C 92 07 00 B8 A0 00 00 84 03 00 00
Offset : 84 03 00 00 -> 00 00 03 84 (0x384 address)
Go to this address and search in the MakerNote section the FNumber 0x3
Tag Type Count Value
03 00 03 00 04 00 00 00 C8 05 00 00
Go to the offset 0x5C8 to find our value (count 4 x type 3 ushort, 16 bits)
0x0x5C8 : 00 00 00 00 00 00 00 00
And ... fail, in fact my canon does not filled this section.
Reading http://www.exiv2.org/tags.html The FNumber can be found in EXIF subsection.
Do the same process to find the EXIF subsection and the tag "0x829d Exif.Image.FNumber type 5 Rational"
Rational type is composed of 64 bits (numerator and denominator ulongs) Rational_data_type
Tag Type Count Value
9D 82 05 00 01 00 00 00 34 03 00 00
And then read the 0x334 offset
1C 00 00 00 0A 00 00 00
As we can read in Hexa : 0x1C / 0XA
In decimal, do the math : 28/10 = 14/5 = 2.8
Verify I have this value in ExifRead
EXIF.py 100EOS5D/IMG_8813.CR2 -vv | grep -i 14/5
EXIF FNumber (Ratio): 14/5
And voila !
I was looking for 2.8 float and this value is stored in fraction format. So the library don't do the math and just simplify the fraction.
This is why we have 14/5 and not 2.8 as expected.
I suggest you use a library that is focused on EXIF reading. The stuff available in libraw/rawkit is really just a nice extra. I can recommend the ExifRead library. It's pure Python and also damn fast. And it gives you better to understand values.
If compatibility with many formats is more of an issue to you than performance you could call exiftool as a subprocess with -j option to give you a json string which you can turn into a dictionary.
That should set you up for most raw formats and even stuff that isn't images at all. And it is going to squeeze every last bit of exif info out of the file. However in comparison with other options it is rather sluggish (like 200x slower):
from PIL import Image
import PIL.ExifTags
import subprocess
import json
import datetime
import exifread
filePath = "someImage.jpg"
filePath = "someRawImage.CR2"
filePath = "someMovie.mov"
filePath = "somePhotoshopImage.psd"
try:
start = datetime.datetime.now()
img = Image.open(filePath)
exif_0 = {
PIL.ExifTags.TAGS[k]: v
for k, v in img.getexif().items()
if k in PIL.ExifTags.TAGS
}
end = datetime.datetime.now()
print("Pillow time:")
print(end-start)
print(str(len(exif_0)), "tags retrieved")
print (exif_0, "\n")
except:
pass
try:
start = datetime.datetime.now()
exif_1 = json.loads(subprocess.run(["/usr/local/bin/exiftool", "-j", filePath], stdout=subprocess.PIPE).stdout.decode("utf-8"))
end = datetime.datetime.now()
print("subprocess time:")
print(end-start)
print(str(len(exif_1[0])), "tags retrieved")
print(exif_1, "\n")
except:
pass
try:
start = datetime.datetime.now()
f = open(filePath, "rb")
exif_2 = exifread.process_file(f)
end = datetime.datetime.now()
print("Exifread time:")
print(end-start)
print(str(len(exif_2)), "tags retrieved")
print(exif_2, "\n")
except:
pass
I'm trying to translate the following python script to R, but I'm having difficulty that reflects that fact that I am not well versed with Python or R.
Here is what I have for Python:
import hashlib, hmac
print hmac.new('123456', 'hello'.encode('utf-8'),hashlib.sha256).digest()
When I run this in Python I'm getting a message that says standard output is empty.
Question: What am I doing wrong?
Here's what I'm using for R
library('digest')
hmac('123456','hello', algo='sha256', serialize=FALSE)
My questions with the R code are:
How do I encode to utf-8 in R. I couldn't find a package.
What are the correct parameter settings for serialize and raw for R given I want to match the output of the Python function above (once its working).
If you want to get the bytes of the hash in R, set raw=TRUE. Then you can write it out as a binary fine
library('digest')
x <- hmac('123456', enc2utf8('hello'), algo='sha256', serialize=FALSE, raw=TRUE)
writeBin(x, "Rout.txt")
If you're not outputting text, the encoding doesn't matter. These are raw bytes. The only different in the output is that the python print seems to be adding a new line character. If I hexdump on the R file i see
0000000 ac 28 d6 02 c7 67 42 4d 0c 80 9e de bf 73 82 8b
0000010 ed 5c e9 9c e1 55 6f 4d f8 e2 23 fa ee c6 0e dd
I am creating a Python function to perform counter mode encryption using the PyCrypto module. I am aware of the builtin, but want to implement it myself.
I'm trying Test Vector #1 from RFC 3686, and have the correct Counter Block and the correct Key in ASCII form. But when I encrypt the Counter Block using the Key, I don't get the expected Key Stream.
The relevant parts of my code:
cipher = AES.new(key)
ctr_block = iv + nonce + ctr
key_stream = base64.b64decode(cipher.encrypt(ctr_block))
I can provide more code if needed, but I'm not sure how because ctr_block and key have many question mark characters when I print them.
Why am I not getting the expected answer? It seems like everything should go right. Perhaps I made some mistake with the encoding of the string.
Edit
Self-contained code:
from Crypto.Cipher import AES
import base64
def hex_to_str(hex_str):
return str(bytearray([int(n, 16) for n in hex_str.split()]))
key = hex_to_str("AE 68 52 F8 12 10 67 CC 4B F7 A5 76 55 77 F3 9E")
iv = hex_to_str("00 00 00 00 00 00 00 00")
nonce = hex_to_str("00 00 00 30")
ctr = hex_to_str("00 00 00 01")
cipher = AES.new(key)
ctr_block = iv + nonce + ctr
key_stream = base64.b64decode(cipher.encrypt(ctr_block))
print "".join([hex(ord(char)) for char in key_stream])
# 0xd90xda0x72
First, the correct CTR block order is nonce + iv + ctr. Second, that base64.b64decode call is wrong: cipher.encrypt produces a decoded string. After these two fixes your code prints 0xb70x600x330x280xdb0xc20x930x1b0x410xe0x160xc80x60x7e0x620xdf which seems to be a correct key stream.
First, use byte strings:
In [14]: keystring = "AE 68 52 F8 12 10 67 CC 4B F7 A5 76 55 77 F3 9E"
In [15]: keystring.replace(' ', '').decode('hex')
Out[15]: '\xaehR\xf8\x12\x10g\xccK\xf7\xa5vUw\xf3\x9e'
Second, you shouldn't use base64.