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;
47 content =
new byte[length];
50 }
catch (IOException ex) {
57 ByteBuffer bb = ByteBuffer.wrap(content);
58 bb.order(ByteOrder.LITTLE_ENDIAN);
59 int header = bb.getInt();
60 ByteBuffer linkClassIdentifier = bb.get(
new byte[16]);
61 int linkFlags = bb.getInt();
62 int fileAttributes = bb.getInt();
63 long crtime = bb.getLong();
64 long atime = bb.getLong();
65 long mtime = bb.getLong();
66 int fileSize = bb.getInt();
67 int iconIndex = bb.getInt();
68 int showCommand = bb.getInt();
69 short hotkey = bb.getShort();
71 List<String> linkTargetIdList =
new ArrayList<String>();
72 if((linkFlags & LnkEnums.LinkFlags.HasLinkTargetIDList.getFlag()) ==
73 LnkEnums.LinkFlags.HasLinkTargetIDList.getFlag()) {
74 int idListSize = bb.getShort();
76 List<byte[]> linkTargetIdListBytes =
new ArrayList<byte[]>();
78 short itemIdSize = bb.getShort();
83 byte[] theArray =
new byte[itemIdSize-2];
85 linkTargetIdListBytes.add(theArray);
86 bytesRead = bytesRead + itemIdSize;
90 boolean hasUnicodeLocalBaseAndCommonSuffixOffset =
false;
91 String localBasePath = null;
92 String commonPathSuffix = null;
93 String localBasePathUnicode = null;
94 String commonPathSuffixUnicode = null;
95 int driveSerialNumber = -1;
97 String volumeLabel = null;
98 int commonNetworkRelativeLinkFlags = -1;
100 boolean unicodeNetAndDeviceName =
false;
101 String netName = null;
102 String netNameUnicode = null;
103 String deviceName = null;
104 String deviceNameUnicode = null;
106 if((linkFlags & LnkEnums.LinkFlags.HasLinkInfo.getFlag()) ==
107 LnkEnums.LinkFlags.HasLinkInfo.getFlag()) {
108 int startOfLinkInfo = bb.position();
109 int linkInfoSize = bb.getInt();
110 int linkInfoHeaderSize = bb.getInt();
111 hasUnicodeLocalBaseAndCommonSuffixOffset = linkInfoHeaderSize >= 0x24;
112 int linkInfoFlags = bb.getInt();
113 int volumeIdOffset = bb.getInt();
114 int localBasePathOffset = bb.getInt();
115 int commonNetworkRelativeLinkOffset = bb.getInt();
116 int commonPathSuffixOffset = bb.getInt();
117 int localBasePathOffsetUnicode = 0;
118 int commonPathSuffixOffsetUnicode = 0;
119 if (hasUnicodeLocalBaseAndCommonSuffixOffset) {
120 localBasePathOffsetUnicode = bb.getInt();
121 commonPathSuffixOffsetUnicode = bb.getInt();
123 if ((linkInfoFlags & LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag())
124 == LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag()) {
125 bb.position(startOfLinkInfo+volumeIdOffset);
126 int volumeIdSize = bb.getInt();
128 driveSerialNumber = bb.getInt();
129 int volumeLabelOffset = bb.getInt();
130 if (volumeLabelOffset != 0x14) {
131 volumeLabel =
parseString(startOfLinkInfo + volumeIdOffset + volumeLabelOffset,
false, volumeIdSize - 0x10);
133 int volumeLabelOffsetUnicode = bb.getInt();
134 volumeLabel =
parseString(startOfLinkInfo + volumeIdOffset + volumeLabelOffsetUnicode,
false, volumeIdSize - 0x14);
138 if ((linkInfoFlags & LnkEnums.LinkInfoFlags.CommonNetworkRelativeLinkAndPathSuffix.getFlag())
139 == LnkEnums.LinkInfoFlags.CommonNetworkRelativeLinkAndPathSuffix.getFlag()) {
140 bb.position(startOfLinkInfo+commonNetworkRelativeLinkOffset);
141 int commonNetworkRelativeLinkSize = bb.getInt();
142 commonNetworkRelativeLinkFlags = bb.getInt();
143 int netNameOffset = bb.getInt();
144 unicodeNetAndDeviceName = netNameOffset > 0x14;
145 int deviceNameOffset = bb.getInt();
146 int netType = bb.getInt();
147 int netNameOffsetUnicode = 0;
148 int deviceNameOffsetUnicode = 0;
149 if (unicodeNetAndDeviceName) {
150 netNameOffsetUnicode = bb.getInt();
151 deviceNameOffsetUnicode = bb.getInt();
153 netName =
parseNetName(startOfLinkInfo + commonNetworkRelativeLinkOffset + netNameOffset,
false);
154 if (unicodeNetAndDeviceName) {
155 netNameUnicode =
parseNetName(startOfLinkInfo + commonNetworkRelativeLinkOffset + netNameOffsetUnicode,
true);
157 if ((commonNetworkRelativeLinkFlags & LnkEnums.CommonNetworkRelativeLinkFlags.ValidNetType.getFlag())
158 == LnkEnums.CommonNetworkRelativeLinkFlags.ValidNetType.getFlag()) {
161 if ((commonNetworkRelativeLinkFlags & LnkEnums.CommonNetworkRelativeLinkFlags.ValidDevice.getFlag())
162 == LnkEnums.CommonNetworkRelativeLinkFlags.ValidDevice.getFlag()) {
163 deviceName =
parseDeviceName(startOfLinkInfo + commonNetworkRelativeLinkOffset + deviceNameOffset,
false);
164 if (unicodeNetAndDeviceName) {
165 deviceNameUnicode =
parseDeviceName(startOfLinkInfo + commonNetworkRelativeLinkOffset + deviceNameOffsetUnicode,
true);
170 if (((linkInfoFlags & LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag())
171 == LnkEnums.LinkInfoFlags.VolumeIDAndLocalBasePath.getFlag())
172 && hasUnicodeLocalBaseAndCommonSuffixOffset) {
173 localBasePathUnicode =
parseLocalBasePath(startOfLinkInfo + localBasePathOffsetUnicode,
true);
174 commonPathSuffixUnicode =
parseCommonPathSuffix(startOfLinkInfo + commonPathSuffixOffsetUnicode,
true);
177 bb.position(startOfLinkInfo+linkInfoSize);
180 if((linkFlags & LnkEnums.LinkFlags.HasName.getFlag()) ==
181 LnkEnums.LinkFlags.HasName.getFlag()) {
184 String relativePath = null;
185 if((linkFlags & LnkEnums.LinkFlags.HasRelativePath.getFlag()) ==
186 LnkEnums.LinkFlags.HasRelativePath.getFlag()) {
189 String workingDir = null;
190 if((linkFlags & LnkEnums.LinkFlags.HasWorkingDir.getFlag()) ==
191 LnkEnums.LinkFlags.HasWorkingDir.getFlag()) {
194 String arguments = null;
195 if((linkFlags & LnkEnums.LinkFlags.HasArguments.getFlag()) ==
196 LnkEnums.LinkFlags.HasArguments.getFlag()) {
199 String iconLocation = null;
200 if((linkFlags & LnkEnums.LinkFlags.HasIconLocation.getFlag()) ==
201 LnkEnums.LinkFlags.HasIconLocation.getFlag()) {
205 return new JLNK(header, linkClassIdentifier.array(), linkFlags, fileAttributes,
206 crtime, atime, mtime, fileSize, iconIndex, showCommand, hotkey,
208 hasUnicodeLocalBaseAndCommonSuffixOffset, localBasePath,
209 commonPathSuffix, localBasePathUnicode, commonPathSuffixUnicode,
210 name, relativePath, workingDir, arguments, iconLocation, driveSerialNumber,
211 driveType, volumeLabel, commonNetworkRelativeLinkFlags,
212 networkProviderType, unicodeNetAndDeviceName, netName, netNameUnicode,
213 deviceName, deviceNameUnicode);
214 }
catch (Exception e) {
215 throw new JLnkParserException(e);
220 short countCharacters = bb.getShort();
221 if(countCharacters == 0) {
224 byte[] theString =
new byte[countCharacters*2];
227 return new String(theString,
"UTF-16LE");
228 }
catch (UnsupportedEncodingException ex) {
229 logger.info(
"Shouldn't happen");
234 private String
parseString(
int offset,
boolean unicode,
int maxlen) {
235 ByteBuffer bb = ByteBuffer.wrap(content);
236 bb.order(ByteOrder.LITTLE_ENDIAN);
238 StringBuilder sb =
new StringBuilder(bb.limit());
240 while (bb.remaining() > 0 && (i < maxlen || maxlen == -1))
254 return sb.toString();
276 List<String> ret =
new ArrayList<String>();
277 if(!idList.isEmpty()) {
281 ret.add(
new String(Arrays.copyOfRange(idList.remove(0), 1, 17)).split(
"\0")[0]);
299 List<String> ret =
new ArrayList<String>();
300 for (byte[] pathElement : idList) {
301 ByteBuffer bb = ByteBuffer.wrap(pathElement);
302 bb.order(ByteOrder.LITTLE_ENDIAN);
303 int offset = bb.getShort(bb.limit() - 2)-2;
304 if (pathElement[offset + 0x02] < 0x03
305 || pathElement[offset + 0x10] >= pathElement[offset]
306 || pathElement[offset + 0x10] < 0x14) {
310 if (pathElement[offset + 0x10] != 0) {
311 ret.add(
getStringAt(bb, offset + pathElement[offset + 0x10],
true));
314 if (pathElement[offset + 0x12] >= pathElement[offset]
315 || pathElement[offset + 0x12] < 0x14) {
319 ret.add(
getStringAt(bb, offset + pathElement[offset + 0x12],
false));
331 private String
getStringAt(ByteBuffer bb,
int offset,
boolean unicode) {
332 byte[] nameArr = Arrays.copyOfRange(bb.array(), offset, bb.limit());
335 return new String(nameArr,
"UTF-16LE").split(
"\0")[0];
336 }
catch (UnsupportedEncodingException ex) {
340 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)
String get0xC(ByteBuffer bb)
static DriveType valueOf(int type)
static CommonCLSIDS valueOf(byte[] type)
static Logger getLogger(String name)