19 package org.sleuthkit.autopsy.coreutils;
22 import java.nio.ByteBuffer;
23 import java.nio.ByteOrder;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.List;
27 import java.util.logging.Level;
44 content =
new byte[length];
47 }
catch (IOException ex) {
54 ByteBuffer bb = ByteBuffer.wrap(content);
55 bb.order(ByteOrder.LITTLE_ENDIAN);
56 int header = bb.getInt();
57 ByteBuffer linkClassIdentifier = bb.get(
new byte[16]);
58 int linkFlags = bb.getInt();
59 int fileAttributes = bb.getInt();
60 long crtime = bb.getLong();
61 long atime = bb.getLong();
62 long mtime = bb.getLong();
63 int fileSize = bb.getInt();
64 int iconIndex = bb.getInt();
65 int showCommand = bb.getInt();
66 short hotkey = bb.getShort();
68 List<String> linkTargetIdList =
new ArrayList<>();
69 if ((linkFlags & LnkEnums.LinkFlags.HasLinkTargetIDList.getFlag())
70 == LnkEnums.LinkFlags.HasLinkTargetIDList.getFlag()) {
71 int idListSize = bb.getShort();
73 List<byte[]> linkTargetIdListBytes =
new ArrayList<>();
75 short itemIdSize = bb.getShort();
76 if (itemIdSize == 0) {
80 byte[] theArray =
new byte[itemIdSize - 2];
82 linkTargetIdListBytes.add(theArray);
83 bytesRead += itemIdSize;
87 boolean hasUnicodeLocalBaseAndCommonSuffixOffset =
false;
88 String localBasePath = null;
89 String commonPathSuffix = null;
90 String localBasePathUnicode = null;
91 String commonPathSuffixUnicode = null;
92 int driveSerialNumber = -1;
94 String volumeLabel = null;
95 int commonNetworkRelativeLinkFlags = -1;
97 boolean unicodeNetAndDeviceName =
false;
98 String netName = null;
99 String netNameUnicode = null;
100 String deviceName = null;
101 String deviceNameUnicode = null;
103 if ((linkFlags & LnkEnums.LinkFlags.HasLinkInfo.getFlag())
104 == LnkEnums.LinkFlags.HasLinkInfo.getFlag()) {
105 int startOfLinkInfo = bb.position();
106 int linkInfoSize = bb.getInt();
107 int linkInfoHeaderSize = bb.getInt();
108 hasUnicodeLocalBaseAndCommonSuffixOffset = linkInfoHeaderSize >= 0x24;
109 int linkInfoFlags = bb.getInt();
110 int volumeIdOffset = bb.getInt();
111 int localBasePathOffset = bb.getInt();
112 int commonNetworkRelativeLinkOffset = bb.getInt();
113 int commonPathSuffixOffset = bb.getInt();
114 int localBasePathOffsetUnicode = 0;
115 int commonPathSuffixOffsetUnicode = 0;
116 if (hasUnicodeLocalBaseAndCommonSuffixOffset) {
117 localBasePathOffsetUnicode = bb.getInt();
118 commonPathSuffixOffsetUnicode = bb.getInt();
120 if ((linkInfoFlags & LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag())
121 == LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag()) {
122 bb.position(startOfLinkInfo + volumeIdOffset);
123 int volumeIdSize = bb.getInt();
125 driveSerialNumber = bb.getInt();
126 int volumeLabelOffset = bb.getInt();
127 if (volumeLabelOffset != 0x14) {
128 volumeLabel =
parseString(startOfLinkInfo + volumeIdOffset + volumeLabelOffset,
false, volumeIdSize - 0x10);
130 int volumeLabelOffsetUnicode = bb.getInt();
131 volumeLabel =
parseString(startOfLinkInfo + volumeIdOffset + volumeLabelOffsetUnicode,
false, volumeIdSize - 0x14);
135 if ((linkInfoFlags & LnkEnums.LinkInfoFlags.CommonNetworkRelativeLinkAndPathSuffix.getFlag())
136 == LnkEnums.LinkInfoFlags.CommonNetworkRelativeLinkAndPathSuffix.getFlag()) {
137 bb.position(startOfLinkInfo + commonNetworkRelativeLinkOffset);
138 int commonNetworkRelativeLinkSize = bb.getInt();
139 commonNetworkRelativeLinkFlags = bb.getInt();
140 int netNameOffset = bb.getInt();
141 unicodeNetAndDeviceName = netNameOffset > 0x14;
142 int deviceNameOffset = bb.getInt();
143 int netType = bb.getInt();
144 int netNameOffsetUnicode = 0;
145 int deviceNameOffsetUnicode = 0;
146 if (unicodeNetAndDeviceName) {
147 netNameOffsetUnicode = bb.getInt();
148 deviceNameOffsetUnicode = bb.getInt();
150 netName =
parseNetName(startOfLinkInfo + commonNetworkRelativeLinkOffset + netNameOffset,
false);
151 if (unicodeNetAndDeviceName) {
152 netNameUnicode =
parseNetName(startOfLinkInfo + commonNetworkRelativeLinkOffset + netNameOffsetUnicode,
true);
154 if ((commonNetworkRelativeLinkFlags & LnkEnums.CommonNetworkRelativeLinkFlags.ValidNetType.getFlag())
155 == LnkEnums.CommonNetworkRelativeLinkFlags.ValidNetType.getFlag()) {
158 if ((commonNetworkRelativeLinkFlags & LnkEnums.CommonNetworkRelativeLinkFlags.ValidDevice.getFlag())
159 == LnkEnums.CommonNetworkRelativeLinkFlags.ValidDevice.getFlag()) {
160 deviceName =
parseDeviceName(startOfLinkInfo + commonNetworkRelativeLinkOffset + deviceNameOffset,
false);
161 if (unicodeNetAndDeviceName) {
162 deviceNameUnicode =
parseDeviceName(startOfLinkInfo + commonNetworkRelativeLinkOffset + deviceNameOffsetUnicode,
true);
167 if (((linkInfoFlags & LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag())
168 == LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag())
169 && hasUnicodeLocalBaseAndCommonSuffixOffset) {
170 localBasePathUnicode =
parseLocalBasePath(startOfLinkInfo + localBasePathOffsetUnicode,
true);
171 commonPathSuffixUnicode =
parseCommonPathSuffix(startOfLinkInfo + commonPathSuffixOffsetUnicode,
true);
174 bb.position(startOfLinkInfo + linkInfoSize);
177 if ((linkFlags & LnkEnums.LinkFlags.HasName.getFlag())
178 == LnkEnums.LinkFlags.HasName.getFlag()) {
181 String relativePath = null;
182 if ((linkFlags & LnkEnums.LinkFlags.HasRelativePath.getFlag())
183 == LnkEnums.LinkFlags.HasRelativePath.getFlag()) {
186 String workingDir = null;
187 if ((linkFlags & LnkEnums.LinkFlags.HasWorkingDir.getFlag())
188 == LnkEnums.LinkFlags.HasWorkingDir.getFlag()) {
191 String arguments = null;
192 if ((linkFlags & LnkEnums.LinkFlags.HasArguments.getFlag())
193 == LnkEnums.LinkFlags.HasArguments.getFlag()) {
196 String iconLocation = null;
197 if ((linkFlags & LnkEnums.LinkFlags.HasIconLocation.getFlag())
198 == LnkEnums.LinkFlags.HasIconLocation.getFlag()) {
202 return new JLNK(header, linkClassIdentifier.array(), linkFlags, fileAttributes,
203 crtime, atime, mtime, fileSize, iconIndex, showCommand, hotkey,
205 hasUnicodeLocalBaseAndCommonSuffixOffset, localBasePath,
206 commonPathSuffix, localBasePathUnicode, commonPathSuffixUnicode,
207 name, relativePath, workingDir, arguments, iconLocation, driveSerialNumber,
208 driveType, volumeLabel, commonNetworkRelativeLinkFlags,
209 networkProviderType, unicodeNetAndDeviceName, netName, netNameUnicode,
210 deviceName, deviceNameUnicode);
211 }
catch (Exception e) {
212 throw new JLnkParserException(e);
217 short countCharacters = bb.getShort();
218 if (countCharacters == 0) {
221 byte[] theString =
new byte[countCharacters * 2];
224 return new String(theString,
"UTF-16LE");
225 }
catch (UnsupportedEncodingException ex) {
226 logger.info(
"Shouldn't happen");
231 private String
parseString(
int offset,
boolean unicode,
int maxlen) {
232 ByteBuffer bb = ByteBuffer.wrap(content);
233 bb.order(ByteOrder.LITTLE_ENDIAN);
235 StringBuilder sb =
new StringBuilder(bb.limit());
237 while (bb.remaining() > 0 && (i < maxlen || maxlen == -1))
251 return sb.toString();
273 List<String> ret =
new ArrayList<>();
274 if (!idList.isEmpty()) {
278 ret.add(
new String(Arrays.copyOfRange(idList.remove(0), 1, 17)).split(
"\0")[0]);
296 List<String> ret =
new ArrayList<>();
297 for (byte[] pathElement : idList) {
298 ByteBuffer bb = ByteBuffer.wrap(pathElement);
299 bb.order(ByteOrder.LITTLE_ENDIAN);
300 int offset = bb.getShort(bb.limit() - 2) - 2;
301 if (pathElement[offset + 0x02] < 0x03
302 || pathElement[offset + 0x10] >= pathElement[offset]
303 || pathElement[offset + 0x10] < 0x14) {
307 if (pathElement[offset + 0x10] != 0) {
308 ret.add(
getStringAt(bb, offset + pathElement[offset + 0x10],
true));
311 if (pathElement[offset + 0x12] >= pathElement[offset]
312 || pathElement[offset + 0x12] < 0x14) {
316 ret.add(
getStringAt(bb, offset + pathElement[offset + 0x12],
false));
328 private String
getStringAt(ByteBuffer bb,
int offset,
boolean unicode) {
329 byte[] nameArr = Arrays.copyOfRange(bb.array(), offset, bb.limit());
332 return new String(nameArr,
"UTF-16LE").split(
"\0")[0];
333 }
catch (UnsupportedEncodingException ex) {
337 return new String(nameArr).split(
"\0")[0];
String getStringAt(ByteBuffer bb, int offset, boolean unicode)
NetworkProviderType(int flag)
List< String > parsePathElements(List< byte[]> idList)
static final Logger logger
List< String > parseLinkTargetIdList(List< byte[]> idList)
String readStringData(ByteBuffer bb)
String parseCommonPathSuffix(int offset, boolean unicode)
String parseNetName(int offset, boolean unicode)
JLnkParser(InputStream is, int length)
String parseString(int offset, boolean unicode, int maxlen)
String parseDeviceName(int offset, boolean unicode)
String parseLocalBasePath(int offset, boolean unicode)
synchronized static Logger getLogger(String name)
String get0xC(ByteBuffer bb)
static DriveType valueOf(int type)
static CommonCLSIDS valueOf(byte[] type)