-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: replace pylnk3 with LnkParse3
Signed-off-by: Jack Cherng <jfcherng@gmail.com>
- Loading branch information
Showing
63 changed files
with
3,812 additions
and
2,115 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .lnk_file import LnkFile as lnk_file |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
from datetime import datetime | ||
from datetime import timezone | ||
from struct import unpack | ||
import functools | ||
import sys | ||
import warnings | ||
|
||
from .utils import parse_uuid, parse_packed_uuid, parse_filetime, parse_dostime | ||
|
||
|
||
def must_be(expected): | ||
def outer(func): | ||
@functools.wraps(func) | ||
def inner(self, *args, **kwargs): | ||
result = func(self, *args, **kwargs) | ||
|
||
if result != expected: | ||
msg = "%s must be %s: %s" % (func.__name__, expected, result) | ||
warnings.warn(msg) | ||
|
||
return result | ||
|
||
return inner | ||
|
||
return outer | ||
|
||
|
||
def uuid(func): | ||
@functools.wraps(func) | ||
def inner(self, *args, **kwargs): | ||
binary = func(self, *args, **kwargs) | ||
|
||
return parse_uuid(binary) | ||
|
||
return inner | ||
|
||
|
||
def packed_uuid(func): | ||
@functools.wraps(func) | ||
def inner(self, *args, **kwargs): | ||
text = func(self, *args, **kwargs) | ||
|
||
return parse_packed_uuid(text) | ||
|
||
return inner | ||
|
||
|
||
def filetime(func): | ||
@functools.wraps(func) | ||
def inner(self, *args, **kwargs): | ||
binary = func(self, *args, **kwargs) | ||
|
||
return parse_filetime(binary) | ||
|
||
return inner | ||
|
||
|
||
def dostime(func): | ||
@functools.wraps(func) | ||
def inner(self, *args, **kwargs): | ||
binary = func(self, *args, **kwargs) | ||
|
||
return parse_dostime(binary) | ||
|
||
return inner |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
class LnkParserError(Exception): | ||
... |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from struct import unpack | ||
from ..extra.lnk_extra_base import LnkExtraBase | ||
|
||
""" | ||
------------------------------------------------------------------ | ||
| 0-7b | 8-15b | 16-23b | 24-31b | | ||
------------------------------------------------------------------ | ||
| <u_int32> BlockSize == 0x0000000C | | ||
------------------------------------------------------------------ | ||
| <u_int32> BlockSignature == 0xA0000004 | | ||
------------------------------------------------------------------ | ||
| <u_int32> CodePage | | ||
------------------------------------------------------------------ | ||
""" | ||
|
||
|
||
class CodePage(LnkExtraBase): | ||
def name(self): | ||
return "CONSOLE_CODEPAGE_BLOCK" | ||
|
||
def code_page(self): | ||
start, end = 8, 12 | ||
return unpack("<I", self._raw[start:end])[0] | ||
|
||
def as_dict(self): | ||
tmp = super().as_dict() | ||
tmp["code_page"] = self.code_page() | ||
return tmp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
from struct import unpack | ||
from ..extra.lnk_extra_base import LnkExtraBase | ||
|
||
""" | ||
------------------------------------------------------------------ | ||
| 0-7b | 8-15b | 16-23b | 24-31b | | ||
------------------------------------------------------------------ | ||
| <u_int32> BlockSize == 0x000000CC | | ||
------------------------------------------------------------------ | ||
| <u_int32> BlockSignature == 0xA0000002 | | ||
-----------------------------------------------------------------| | ||
| <u_int16> FillAttributes |<u_int16> PopupFillAttributes | | ||
------------------------------------------------------------------ | ||
| <int16> ScreenBufferSizeX | <int16> ScreenBufferSizeY | | ||
------------------------------------------------------------------ | ||
| <int16> WindowSizeX | <int16> WindowSizeY | | ||
------------------------------------------------------------------ | ||
| <int16> WindowOriginX | <int16> WindowOriginY | | ||
------------------------------------------------------------------ | ||
| Unused1 | | ||
------------------------------------------------------------------ | ||
| Unused2 | | ||
------------------------------------------------------------------ | ||
| <u_int32> FontSize | | ||
------------------------------------------------------------------ | ||
| <u_int32> FontFamily | | ||
------------------------------------------------------------------ | ||
| <u_int32> FontWeight | | ||
------------------------------------------------------------------ | ||
| <unicode_str> Face Name | | ||
| 64 B | | ||
------------------------------------------------------------------ | ||
| <u_int32> CursorSize | | ||
------------------------------------------------------------------ | ||
| <u_int32> FullScreen | | ||
------------------------------------------------------------------ | ||
| <u_int32> QuickEdit | | ||
------------------------------------------------------------------ | ||
| <u_int32> InsertMode | | ||
------------------------------------------------------------------ | ||
| <u_int32> AutoPosition | | ||
------------------------------------------------------------------ | ||
| <u_int32> HistoryBufferSize | | ||
------------------------------------------------------------------ | ||
| <u_int32> NumberOfHistoryBuffers | | ||
------------------------------------------------------------------ | ||
| <u_int32> HistoryNoDup | | ||
------------------------------------------------------------------ | ||
| <vector<u_int32>> ColorTable | | ||
| 64 B | | ||
------------------------------------------------------------------ | ||
""" | ||
|
||
|
||
class Console(LnkExtraBase): | ||
def name(self): | ||
return "CONSOLE_PROPERTIES_BLOCK" | ||
|
||
def fill_attributes(self): | ||
start, end = 8, 10 | ||
return unpack("<H", self._raw[start:end])[0] | ||
|
||
def popup_fill_attributes(self): | ||
start, end = 10, 12 | ||
return unpack("<H", self._raw[start:end])[0] | ||
|
||
def screen_buffer_size_x(self): | ||
start, end = 12, 14 | ||
return unpack("<h", self._raw[start:end])[0] | ||
|
||
def screen_buffer_size_y(self): | ||
start, end = 14, 16 | ||
return unpack("<h", self._raw[start:end])[0] | ||
|
||
def window_size_x(self): | ||
start, end = 16, 18 | ||
return unpack("<h", self._raw[start:end])[0] | ||
|
||
def window_size_y(self): | ||
start, end = 18, 20 | ||
return unpack("<h", self._raw[start:end])[0] | ||
|
||
def window_origin_x(self): | ||
start, end = 20, 22 | ||
return unpack("<h", self._raw[start:end])[0] | ||
|
||
def window_origin_y(self): | ||
start, end = 22, 24 | ||
return unpack("<h", self._raw[start:end])[0] | ||
|
||
def font_size(self): | ||
start, end = 32, 36 | ||
return unpack("<I", self._raw[start:end])[0] | ||
|
||
def font_family(self): | ||
start, end = 36, 40 | ||
return unpack("<I", self._raw[start:end])[0] | ||
|
||
def font_weight(self): | ||
start, end = 40, 44 | ||
return unpack("<I", self._raw[start:end])[0] | ||
|
||
def face_name(self): | ||
start = 44 | ||
end = start + 64 | ||
binary = self._raw[start:end] | ||
text = self.text_processor.read_unicode_string(binary) | ||
return text | ||
|
||
def cursor_size(self): | ||
start, end = 108, 112 | ||
return unpack("<I", self._raw[start:end])[0] | ||
|
||
def full_screen(self): | ||
start, end = 112, 116 | ||
return unpack("<I", self._raw[start:end])[0] | ||
|
||
def quick_edit(self): | ||
start, end = 116, 120 | ||
return unpack("<I", self._raw[start:end])[0] | ||
|
||
def insert_mode(self): | ||
start, end = 120, 124 | ||
return unpack("<I", self._raw[start:end])[0] | ||
|
||
def auto_position(self): | ||
start, end = 124, 128 | ||
return unpack("<I", self._raw[start:end])[0] | ||
|
||
def history_buffer_size(self): | ||
start, end = 128, 132 | ||
return unpack("<I", self._raw[start:end])[0] | ||
|
||
def number_of_history_buffers(self): | ||
start, end = 132, 136 | ||
return unpack("<I", self._raw[start:end])[0] | ||
|
||
def history_no_dup(self): | ||
start, end = 136, 140 | ||
return unpack("<I", self._raw[start:end])[0] | ||
|
||
def color_table(self): | ||
start, end = 140, 144 | ||
return unpack("<I", self._raw[start:end])[0] | ||
|
||
def as_dict(self): | ||
tmp = super().as_dict() | ||
tmp["fill_attributes"] = self.fill_attributes() | ||
tmp["popup_fill_attributes"] = self.popup_fill_attributes() | ||
tmp["screen_buffer_size_x"] = self.screen_buffer_size_x() | ||
tmp["screen_buffer_size_y"] = self.screen_buffer_size_y() | ||
tmp["window_size_x"] = self.window_size_x() | ||
tmp["window_size_y"] = self.window_size_y() | ||
tmp["window_origin_x"] = self.window_origin_x() | ||
tmp["window_origin_y"] = self.window_origin_y() | ||
tmp["font_size"] = self.font_size() | ||
tmp["font_family"] = self.font_family() | ||
tmp["font_weight"] = self.font_weight() | ||
tmp["face_name"] = self.face_name() | ||
tmp["cursor_size"] = self.cursor_size() | ||
tmp["full_screen"] = self.full_screen() | ||
tmp["quick_edit"] = self.quick_edit() | ||
tmp["insert_mode"] = self.insert_mode() | ||
tmp["auto_position"] = self.auto_position() | ||
tmp["history_buffer_size"] = self.history_buffer_size() | ||
tmp["number_of_history_buffers"] = self.number_of_history_buffers() | ||
tmp["history_no_dup"] = self.history_no_dup() | ||
tmp["color_table"] = self.color_table() | ||
return tmp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
from ..decorators import uuid, packed_uuid | ||
from ..extra.lnk_extra_base import LnkExtraBase | ||
|
||
""" | ||
------------------------------------------------------------------ | ||
| 0-7b | 8-15b | 16-23b | 24-31b | | ||
------------------------------------------------------------------ | ||
| <u_int32> BlockSize == 0x00000314 | | ||
------------------------------------------------------------------ | ||
| <u_int32> BlockSignature == 0xA0000006 | | ||
------------------------------------------------------------------ | ||
| <str> DarwinDataAnsi | | ||
| 260 B | | ||
------------------------------------------------------------------ | ||
| <unicode_str> DarwinDataUnicode | | ||
| 520 B | | ||
------------------------------------------------------------------ | ||
DarwinData consists of {Product-Code, Feature Key, Component Code}. It is stored | ||
in a compressed format, e.g. "w_1^VX!!!!!!!!!MKKSkEXCELFiles>tW{~$4Q]c@II=l2xaTO5Z", | ||
which can results into | ||
{91120000-0030-0000-0000-0000000ff1ce}EXCELFiles{0638c49d-bb8b-4cd1-b191-052e8f325736}. | ||
There are four variants according to | ||
https://community.broadcom.com/symantecenterprise/viewdocument/working-with-darwin-descriptors: | ||
1. {compressed product code}{feature name}>{compressed component ID} | ||
2. {compressed product code}>{compressed component ID} | ||
3. {compressed product code}{feature name}< | ||
4. {compressed product code}< | ||
See http://www.laurierhodes.info/?q=node/34 or | ||
https://metadataconsulting.blogspot.com/2019/12/CSharp-Convert-a-GUID-to-a-Darwin-Descriptor-and-back.html | ||
or https://web.archive.org/web/20080323160816/http://support.microsoft.com/kb/243630. | ||
""" | ||
|
||
|
||
class Darwin(LnkExtraBase): | ||
def name(self): | ||
return "DARWIN_BLOCK" | ||
|
||
def darwin_data_ansi(self): | ||
start = 8 | ||
end = start + 260 | ||
binary = self._raw[start:end] | ||
text = self.text_processor.read_string(binary) | ||
return text | ||
|
||
def darwin_data_unicode(self): | ||
start = 268 | ||
end = start + 520 | ||
binary = self._raw[start:end] | ||
text = self.text_processor.read_unicode_string(binary) | ||
return text | ||
|
||
@packed_uuid | ||
def product_code_id(self): | ||
data = self.darwin_data_unicode() | ||
start, end = 0, 20 | ||
text = data[start:end] | ||
return text | ||
|
||
def feature_name(self): | ||
data = self.darwin_data_unicode() | ||
start = 20 | ||
# Search for a termiantor sign which can be either `<` or `>`. | ||
# None of these characters should be located in a packed GUID. | ||
# If the character is not found, `find` returns `-1`, i.e. by using max | ||
# we want to get the one which is present. | ||
# An absence of both characters leads to an exception. | ||
terminator = max(data.find(">"), data.find("<")) | ||
if terminator == start: | ||
# If the terminator is found but is the same as the start position, | ||
# there is no feature name. | ||
return None | ||
end = terminator | ||
text = data[start:end] | ||
return text | ||
|
||
@packed_uuid | ||
def component_id(self): | ||
data = self.darwin_data_unicode() | ||
terminator = data.find(">") | ||
if terminator == -1: | ||
# Set the ID to `None` if `terminator` is not found. | ||
return None | ||
start = terminator + 1 | ||
text = data[start:] | ||
return text | ||
|
||
def as_dict(self): | ||
tmp = super().as_dict() | ||
tmp["darwin_data_ansi"] = self.darwin_data_ansi() | ||
tmp["darwin_data_unicode"] = self.darwin_data_unicode() | ||
tmp["product_code_id"] = self.product_code_id() | ||
tmp["feature_name"] = self.feature_name() | ||
tmp["component_id"] = self.component_id() | ||
return tmp |
Oops, something went wrong.