Feature Request: Further decode "Zone Identifier" streams

Started by PoP, November 04, 2022, 10:48:08 AM

Previous topic - Next topic

PoP

When most Browsers download an image from the Internet they create a Zone Identifier which might be useful to identify the source of the download.

Currently Exiftool only displays Exists on such files.
QuoteH:\z>exiftool -S image.jpg
ExifToolVersion: 12.49
FileName: image.jpg
Directory: .
FileSize: 39 kB
ZoneIdentifier: Exists
FileModifyDate: 2022:11:04 09:38:34-04:00
FileAccessDate: 2022:11:04 10:08:45-04:00
FileCreateDate: 2022:11:04 09:38:34-04:00
FilePermissions: -rw-rw-rw-
FileType: JPEG
FileTypeExtension: jpg
MIMEType: image/jpeg
JFIFVersion: 1.01
ResolutionUnit: None
XResolution: 1
YResolution: 1
ImageWidth: 736
ImageHeight: 736
EncodingProcess: Progressive DCT, Huffman coding
BitsPerSample: 8
ColorComponents: 3
YCbCrSubSampling: YCbCr4:2:0 (2 2)
ImageSize: 736x736
Megapixels: 0.542

H:\z>


Would it be possible to further decode this additional stream (similarly to the following Microsoft Power Shell decode):

QuotePS H:\z> Get-Item -path image.jpg -stream *


PSPath        : Microsoft.PowerShell.Core\FileSystem::H:\z\image.jpg::$DATA
PSParentPath  : Microsoft.PowerShell.Core\FileSystem::H:\z
PSChildName   : image.jpg::$DATA
PSDrive       : H
PSProvider    : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName      : H:\z\image.jpg
Stream        : :$DATA
Length        : 38936

PSPath        : Microsoft.PowerShell.Core\FileSystem::H:\z\image.jpg:Zone.Identifier
PSParentPath  : Microsoft.PowerShell.Core\FileSystem::H:\z
PSChildName   : image.jpg:Zone.Identifier
PSDrive       : H
PSProvider    : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName      : H:\z\image.jpg
Stream        : Zone.Identifier
Length        : 230



PS H:\z> Get-Content -path image.jpg -stream Zone.Identifier
[ZoneTransfer]
ZoneId=3
ReferrerUrl=https://i.pinimg.com/736x/1a/7b/80/1a7b805cb7b704cf30418acf71c38ab1--funny-coffee-mugs.jpg
HostUrl=https://i.pinimg.com/736x/1a/7b/80/1a7b805cb7b704cf30418acf71c38ab1--funny-coffee-mugs.jpg
PS H:\z>

For reference:

Sample Image downloaded from https://i.pinimg.com/736x/1a/7b/80/1a7b805cb7b704cf30418acf71c38ab1--funny-coffee-mugs.jpg

Explanation & field format from https://www.digital-detective.net/forensic-analysis-of-zone-identifier-stream/





StarGeek

You got me curious and I was able to throw a quick config file to read these values.
%Image::ExifTool::UserDefined = (
    'Image::ExifTool::Composite' => {
        ZoneIDReferrerUrl => {
Require => {
0 => 'Directory',
1 => 'FileName',
2 => 'ZoneIdentifier',
},
ValueConv => q{
my $pathToZone = "$val[0]/$val[1]:Zone.Identifier";
if (open my $fh, "<", $pathToZone) {
read $fh, my $file_content, -s $fh;
return $1 if ($file_content=~m/ReferrerUrl=(.*)\r?\n/);
}
return undef;
},
},
ZoneIDHostUrl => {
Require => {
0 => 'Directory',
1 => 'FileName',
2 => 'ZoneIdentifier',
},
ValueConv => q{
my $pathToZone = "$val[0]/$val[1]:Zone.Identifier";
if (open my $fh, "<", $pathToZone) {
read $fh, my $file_content, -s $fh;
return $1 if ($file_content=~m/HostUrl=(.*)\r?\n/);
}
return undef;
},
},
},
);
#------------------------------------------------------------------------------

Example output:
C:\>type Y:\!temp\bbb\1a7b805cb7b704cf30418acf71c38ab1--funny-coffee-mugs.jpg:Zone.Identifier
[ZoneTransfer]
ZoneId=3
ReferrerUrl=https://i.pinimg.com/736x/1a/7b/80/1a7b805cb7b704cf30418acf71c38ab1--funny-coffee-mugs.jpg
HostUrl=https://i.pinimg.com/736x/1a/7b/80/1a7b805cb7b704cf30418acf71c38ab1--funny-coffee-mugs.jpg

C:\>exiftool -config zone_Identifier.config -G1 -a -s -ZoneIDReferrerUrl -ZoneIDHostUrl Y:\!temp\bbb\1a7b805cb7b704cf30418acf71c38ab1--funny-coffee-mugs.jpg
[Composite]     ZoneIDReferrerUrl               : https://i.pinimg.com/736x/1a/7b/80/1a7b805cb7b704cf30418acf71c38ab1--funny-coffee-mugs.jpg
[Composite]     ZoneIDHostUrl                   : https://i.pinimg.com/736x/1a/7b/80/1a7b805cb7b704cf30418acf71c38ab1--funny-coffee-mugs.jpg

Haven't tested it much, so there may be issues.

* Did you read FAQ #3 and use the command listed there?
* Please use the Code button for exiftool code/output.
 
* Please include your OS, Exiftool version, and type of file you're processing (MP4, JPG, etc).

PoP

Thank you StarGeek. Simple extract... Excellent!

ZoneId Number interpretation, etc. will just be easy additions to your receipe now.

StarGeek

Quote from: PoP on November 05, 2022, 08:18:39 AMZoneId Number interpretation, etc. will just be easy additions to your receipe now.

Ah.  I didn't think that was important.  The link you gave doesn't seem to have any actual translation from the number into an name.  Reading the article a bit, it looks like ZoneId=3 means URLZONE_INTERNET, but nothing else for the others except -1, 0, 999, 1000, 10000.
* Did you read FAQ #3 and use the command listed there?
* Please use the Code button for exiftool code/output.
 
* Please include your OS, Exiftool version, and type of file you're processing (MP4, JPG, etc).

PoP

Don't sweat it. I meant I would do myself the receipe changes (after digging MicroSoft documentation). Thanks again.

StarGeek

Let me know what you end up with, so this config file can be updated.
* Did you read FAQ #3 and use the command listed there?
* Please use the Code button for exiftool code/output.
 
* Please include your OS, Exiftool version, and type of file you're processing (MP4, JPG, etc).

PoP

Quote from: PoP on November 05, 2022, 02:49:56 PMI meant I would do myself the receipe changes

Sorry I lied   ;)   I only added ZoneId:

%Image::ExifTool::UserDefined = (
    'Image::ExifTool::Composite' => {
        ZoneID => {
            Require => {
                0 => 'Directory',
                1 => 'FileName',
                2 => 'ZoneIdentifier',
            },
            ValueConv => q{
                my $pathToZone = "$val[0]/$val[1]:Zone.Identifier";
                if (open my $fh, "<", $pathToZone) {
                    read $fh, my $file_content, -s $fh;
                    return $1 if ($file_content=~m/ZoneId=(.*)\r?\n/);
                }
                return undef;
            },
        },
        ZoneIDReferrerUrl => {
            Require => {
                0 => 'Directory',
                1 => 'FileName',
                2 => 'ZoneIdentifier',
            },
            ValueConv => q{
                my $pathToZone = "$val[0]/$val[1]:Zone.Identifier";
                if (open my $fh, "<", $pathToZone) {
                    read $fh, my $file_content, -s $fh;
                    return $1 if ($file_content=~m/ReferrerUrl=(.*)\r?\n/);
                }
                return undef;
            },
        },
        ZoneIDHostUrl => {
            Require => {
                0 => 'Directory',
                1 => 'FileName',
                2 => 'ZoneIdentifier',
            },
            ValueConv => q{
                my $pathToZone = "$val[0]/$val[1]:Zone.Identifier";
                if (open my $fh, "<", $pathToZone) {
                    read $fh, my $file_content, -s $fh;
                    return $1 if ($file_content=~m/HostUrl=(.*)\r?\n/);
                }
                return undef;
            },
        },
    },
);
#------------------------------------------------------------------------------

On a doctored file local on my computer:

H:\z\AYBABTU>exiftool -config zone_Identifier.config -G1 -a -s -ZoneID -ZoneIDReferrerUrl -ZoneIDHostUrl AYBABTU.png
[Composite]     ZoneID                          : 4
[Composite]     ZoneIDReferrerUrl               : https://CATS.html
[Composite]     ZoneIDHostUrl                   : https://ZeroWing.html

I would have liked to convert ZoneId->URLZONE for the following Ids
0->LOCAL
1->INTRANET
2->TRUSTED
3->INTERNET
4->UNTRUSTED
Which I am fairly confident from inspecting the Windows registry HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Zones but I was intimidated by Image::ExifTool coding. That will do for now.






StarGeek

Quote from: PoP on November 06, 2022, 10:52:13 AMI would have liked to convert ZoneId->URLZONE for the following Ids
0->LOCAL
1->INTRANET
2->TRUSTED
3->INTERNET
4->UNTRUSTED
Which I am fairly confident from inspecting the Windows registry HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Zones but I was intimidated by Image::ExifTool coding. That will do for now.

Ok, try this config.  I used exiftool's PrintConv function so that you can either get a text value or if you use the -n (--printConv) option (# shortcut in this example), you can get the raw value.

zone_Identifier.config
%Image::ExifTool::UserDefined = (
    'Image::ExifTool::Composite' => {
        ZoneID => {
            Require => {
                0 => 'Directory',
                1 => 'FileName',
                2 => 'ZoneIdentifier',
            },
            ValueConv => q{
                my $pathToZone = "$val[0]/$val[1]:Zone.Identifier";
                if (open my $fh, "<", $pathToZone) {
                    read $fh, my $file_content, -s $fh;
                    return $1 if ($file_content=~m/ZoneId=(.*)\r?\n/);
                }
                return undef;
            },
            PrintConv => {
                0 => 'LOCAL',
                1 => 'INTRANET',
                2 => 'TRUSTED',
                3 => 'INTERNET',
                4 => 'UNTRUSTED',
                -1 => 'URLZONE_INVALID',
                999 => 'URLZONE_PREDEFINED_MAX',
                1000 => 'URLZONE_USER_MIN',
                10000 => 'URLZONE_USER_MAX',
            },
        },
        ZoneIDReferrerUrl => {
            Require => {
                0 => 'Directory',
                1 => 'FileName',
                2 => 'ZoneIdentifier',
            },
            ValueConv => q{
                my $pathToZone = "$val[0]/$val[1]:Zone.Identifier";
                if (open my $fh, "<", $pathToZone) {
                    read $fh, my $file_content, -s $fh;
                    return $1 if ($file_content=~m/ReferrerUrl=(.*)\r?\n/);
                }
                return undef;
            },
        },
        ZoneIDHostUrl => {
            Require => {
                0 => 'Directory',
                1 => 'FileName',
                2 => 'ZoneIdentifier',
            },
            ValueConv => q{
                my $pathToZone = "$val[0]/$val[1]:Zone.Identifier";
                if (open my $fh, "<", $pathToZone) {
                    read $fh, my $file_content, -s $fh;
                    return $1 if ($file_content=~m/HostUrl=(.*)\r?\n/);
                }
                return undef;
            },
        },
    },
);
#------------------------------------------------------------------------------

Example output:
C:\>exiftool -config zone_Identifier.config -G1 -a -s -zone* -ZoneID# Y:\!temp\bbb\1a7b805cb7b704cf30418acf71c38ab1--funny-coffee-mugs.jpg
[System]        ZoneIdentifier                  : Exists
[Composite]    ZoneID                          : INTERNET
[Composite]    ZoneIDHostUrl                  : https://i.pinimg.com/736x/1a/7b/80/1a7b805cb7b704cf30418acf71c38ab1--funny-coffee-mugs.jpg
[Composite]    ZoneIDReferrerUrl              : https://i.pinimg.com/736x/1a/7b/80/1a7b805cb7b704cf30418acf71c38ab1--funny-coffee-mugs.jpg
[Composite]    ZoneID                          : 3
* Did you read FAQ #3 and use the command listed there?
* Please use the Code button for exiftool code/output.
 
* Please include your OS, Exiftool version, and type of file you're processing (MP4, JPG, etc).