`
pope12389
  • 浏览: 9050 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

.lnk文件格式解析

lnk 
阅读更多
.lnk文件格式解析
             
       由于.lnk文件提供丰富的调用方式,因此在研究该文件类型格式的基础的可以发现有很多字段可以被恶意利用。下面是一个.lnk文件格式的通用结构,也就
   说.lnk文件是由这样不同的节组成的,但这些节并不是全都必须存在。

               .lnk 文件格式
               +---------------------------+
               | lnk file header            |    
               +---------------------------+ >------.
               | Shell Item Id List         |         |
               +---------------------------+         |
               | File location info         |         |
               +---------------------------+         |
               | Description string         |         |
               +---------------------------+        ---
               | Relative path string       |   这几个节不是每一个都必须存在,如果存在就要按这样的顺序关系排列。
               +---------------------------+        ---
               | Working directory string   |         |
               +---------------------------+         |
               | Command line string        |         |
               +---------------------------+         |
               | Icon filename string       |         |
               +---------------------------+ >------.
               | Extra stuff                |
               +---------------------------+

      1 首先是文件头lnk file header结构,这里记录了比较重要的文件信息,无论是恶意代码的感染还是用于检测,都需要对该结构有所了解,下面是文件头
      结构参考数据。
    
       Offset    Size/Type     Description
     
       0x00       1   dword     总是为0000004CH,相当于字符"L",用于标识是否是个有效的.lnk文件。
       0x04       16 bytes     GUID,标识.lnk的唯一标识符,不排除以后MS对该字段有所修改。
       0x14       1   dword     *重要,Flags用来标识.lnk文件中有哪些可选属性,也就是哪些节是可选的。
       0x18       1   dword     目标文件属性(是否只读、隐藏、系统文件、加密、临时...)
       0x1c       1   qword     文件创建时间     
       0x24       1   qword     文件修改时间
       0x2c       1   qword     文件最后一次访问时间
       0x34       1   dword     目标文件长度
       0x38       1   dword     自定义图标个数
       0x3c       1   dword     目标文件执行时窗口显示方式(1-正常显示,2-最小化,3-最大化)
       0x40       1   dword     热键
       0x44       2   dword     该字段未知,常为0
     
       偏移0x14处的值含义:
     
       bit    该bit置1
     
       0      包含shell item id list节,通过修改文件过滤掉该节,不影响.lnk执行目标文件,但影响其它功能。
       1      指向文件或文件夹,如果此位为0表示指向其他。
       2       存在描述字符串
       3       存在相对路径
       4       存在工作路径
       5       存在命令行参数
       6       存在自定义图标   *--> 该位置一般用于病毒判断是否感染目标文件的标志.
     
       2 Shell Item Id List 节是个可选结构,由文件头中offset 0x14位置处的值来决定,0 bit值为1时,表示该lnk文件包含该结构。
       如果存在该结构,偏移0x4c的位置的一个unsigned short int是Shell Item Id List结构的大小标识,后面紧跟一个SHITEMID结构,该结构体定义如下
     
       typedef struct _SHITEMID
       {
         unsigned short int cb;
         unsigned char   abID[0];
       }SHITEMID,*LPSHITEMID;
     
       cb标识一项SHITEMID结构大小,abID是可变结构,存储数据具体数据,里面的含义有些未知,但第0项里面的数据是不能修改的,否则.lnk文件无法运行。
       Shell Item Id List 结构
     
    /- +-------------------------------+
    |   |size (该节总长度)               |------> 该项如果修改,会导致.lnk无法运行,如果含有命令参数,也会混乱。
    |   +-------------------------------+
    |   |SHITEMID[0]                     |------> 该项所有值均固定,unsigned char data[22] = {
    V   +-------------------------------+            0x14, 0x00, 0x1F, 0x50, 0xE0, 0x4F, 0xD0, 0x20, 0xEA, 0x3A, 0x69, 0x10, 0xA2, 0xD8, 0x08,
size   |SHITEMID[1]                     |------\     0x00, 0x2B, 0x30, 0x30, 0x9D, 0x19, 0x00};
    A   +-------------------------------+       |     也就是cb=0x0014,修改任意值都会导致.lnk无法运行。
    |   |...                             |       |  
    |   |                                |       .------> 该项cb的值一般固定为0x2f(也可能是别的值),不可修改。abID的值为指向目标程序所在盘符的字符串
    |   |                                |                如"C:\",该段空间数据可以任意修改。
    |   |                                |------\
    |   +-------------------------------+       | -----> 修改会影响.lnk文件执行。
    |   |SHITEMID[n]                     |------/
    \- +-------------------------------+
     
       3 File location info,一般指文件信息节,是个可选结构,由文件头中offset 0x14位置处的值来决定,1 bit值为1时,表示该lnk文件包含该结构。
     
       Offset Size/Type     Description
     
       0x00    1dword       该节总长度,该值的修改,会影响.lnk文件执行或命令参数混乱失效。
       0x04    1dword       固定为0x1c,指明为该节长度,该值可任意修改。       
       0x08    1dword       flags标志,指示文件在哪些卷有效,例如是本地卷标还是网络卷标。
       0x0c    1dword       固定为0x1c,本地卷信息表偏移。     
       0x10    1dword       指明目标文件路径相对本节头部的偏移,但.lnk文件执行目标程序并不依赖于该值指向的路径是否正确。
       0x14    1dword       网络卷信息表偏移,如果flags标记含有网络卷的话,否则为0.           
       0x18    1dword       剩余偏移路径,一般都指向本节的末尾,也就是节总长度减1的值,当该值指向的位置为0时(大多数情况下都是0),该值可任意修改。
     
       flags 具体含义:
     
       如果目标文件是本地文件,那么文件名称 = 本地路径信息+剩余偏移路径
       如果目标文件是网络文件,那么文件名称 = 网络卷中共享名称+剩余偏移路径
     
       接着File location info节的数据是,本地卷信息表,及网络卷信息表。
       本地卷信息表结构如下:
     
       Offset    Size/Type      Description
     
       0x00      1dword         本地卷信息表的长度,该值可任意修改。
       0x04      1dword         卷类型(网络盘,软盘,硬盘,可移动...后面有说明),该值可以任意修改。
       0x08      1dword         标识卷序列号,2byte一组,该值可任意修改。     
       0x0c      1dword         卷名称的偏移,固定为0x10,该值可以任意修改。
       0x10      可变长度       卷名称,其大小由该表总长度决定。
     
       网络卷信息表结构如下:
     
       Offset    Size/Type      Description
     
       0x00      1dword         网络卷信息表的长度,该值可任意修改。
       0x04      1dword         固定为0x2     
       0x08      1dword         固定为0x14     
       0x0c      1dword         固定为0     
       0x10      可变长度       固定为0x20000     
       0x10      可变长度       网络共享名
     
     
       4 Description string 一般指描述字符节,是个可选结构,由文件头中offset 0x14位置处的值来决定,2 bit值为1时,表示该lnk文件包含该结构。
     
       该节开始是个unsigned short int 表示该节的长度,不包含这2byte,由于该字符串的描述字符为unicode字符,所以取得该值后还得乘以2.
       该字符也就是右键查看快捷方式信息中的“起始位置(S)”中的那个描述,该值修改不影响.lnk文件执行。
     
       5 Relative path string 一般指相对路径节,是个可选结构,由文件头中offset 0x14位置处的值来决定,3 bit值为1时,表示该lnk文件包含该结构。
       该节结构同上。
     
       6 Working directory string 一般指工作路径节,是个可选结构,由文件头中offset 0x14位置处的值来决定,4 bit值为1时,表示该lnk文件包含该结构。
       该节结构同上。
     
       7 Command line string 一般指命令行节,是个可选结构,由文件头中offset 0x14位置处的值来决定,5 bit值为1时,表示该lnk文件包含该结构。
       该节结构同上。
     
       8 Icon filename string 一般指自定义图标节,是个可选结构,由文件头中offset 0x14位置处的值来决定,6 bit值为1时,表示该lnk文件包含该结构。
       该节结构同上。
     
       9 附加数据节,里面的数据具体含义未知,有些里面会包含一些本机机器名称。
     
       以上就是对.lnk文件格式的简要分析,对.lnk进行感染最主要的就是偷换.lnk指向的目标文件路径,这点和映像劫持有些类似。同时保留原目标文件路径,
       留在后面调用,以防感染后被人察觉到快捷方式失效,这样在恶意程序后台启动后,还会调用原目标文件。
          
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.text.DecimalFormat;
import java.text.NumberFormat;

public class LnkParser {

    public LnkParser(File f) throws Exception {
        parse(f);
    }

    private boolean is_dir;
    public boolean isDirectory() {
        return is_dir;
    }

    private String real_file;
    public String getRealFilename() {
        return real_file;
    }

    public void parse(File f) throws Exception {
        // read the entire file into a byte buffer
        FileInputStream fin = new FileInputStream(f);
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        byte[] buff = new byte[256];
        while(true) {
            int n = fin.read(buff);
            if(n == -1) { break; }
            bout.write(buff,0,n);
        }
        fin.close();
        byte[] link = bout.toByteArray();


        // get the flags byte
        byte flags = link[0x14];

        // get the file attributes byte
        final int file_atts_offset = 0x18;
        byte fileatts = link[file_atts_offset];
        byte is_dir_mask = (byte)0x10;
        if((fileatts & is_dir_mask) > 0) {
            is_dir = true;
        } else {
            is_dir = false;
        }

        // if the shell settings are present, skip them
        final int shell_offset = 0x4c;
        int shell_len = 0;
        if((flags & 0x1) > 0) {
            // the plus 2 accounts for the length marker itself
            shell_len = bytes2short(link,shell_offset) + 2;
        }

        // get to the file settings
        int file_start = 0x4c + shell_len;

        // get the local volume and local system values
        int local_sys_off = link[file_start+0x10] + file_start;
        real_file = getNullDelimitedString(link,local_sys_off);
        p("real filename = " + real_file);
    }

    static String getNullDelimitedString(byte[] bytes, int off) {
        int len = 0;
        // count bytes until the null character (0)
        while(true) {
            if(bytes[off+len] == 0) {
                break;
            }
            len++;
        }
        return new String(bytes,off,len);
    }

    // convert two bytes into a short
    // note, this is little endian because it's for an
    // Intel only OS.
    static int bytes2short(byte[] bytes, int off) {
        return bytes[off] | (bytes[off+1]<<8);
    }

    /*
    static int norm(byte b) {
        if(b < 0) {
            b+=128;
        }
        return b;
    }
    static int bytes2int(byte[] arr, int off) {
        int b1 = norm(arr[off]);
        int b2 = norm(arr[off+1]);
        int b3 = norm(arr[off+2]);
        int b4 = norm(arr[off+3]);
        int val =  (
                    (b1 << 0) |
                    (b2 << 8 ) |
                    (b3 << 16) |
                    (b4 << 24)
                    );
        //p("bytes2int: " + b1 + " " + b2 + " " + b3 + " " + b4);
        return val;
    }


    static NumberFormat num_format = new DecimalFormat(" 000;-000");

    public static String padd(String str, int len) {
        while(str.length() < len) {
            str = " " + str;
        }
        return str;
    }

    public static void pw(byte[] arr, int off) {
        StringBuffer top = new StringBuffer();
        StringBuffer mid = new StringBuffer();
        StringBuffer bot = new StringBuffer();
        top.append("--");
        mid.append("  ");
        bot.append("  ");

        for(int i=0; i<16; i++) {
            int val = arr[off+i];
            String str = Integer.toHexString(off+i);
            top.append(padd(str,5));
            mid.append(padd(""+val,5));
            if(val < 0) {
                val += 128;
            }
            if(val >= ' ' && val <= '~') {
                str = "" + (char)val;
            } else {
                str = Integer.toHexString(val);
            }
            str = padd(str,5);
            bot.append(str);
            if(i%4==3) {
                top.append("    ");
                mid.append("    ");
                bot.append("    ");
            }
        }
        p(top.toString());
        p(mid.toString());
        p(bot.toString());
    }
    public static void pbits(byte bt) {
        p("byte = " + bt + " " + Integer.toHexString(bt) + " " + Integer.toBinaryString(bt));
    }*/

    public static void p(String str) {
        System.out.println(str);
    }
}
分享到:
评论

相关推荐

    Python-LnkParse是Windows快捷文件LNK解析器

    1. **解析LNK文件结构**:`Python-LnkParse`能够读取LNK文件,并解码其内部结构,包括链接的目标位置、创建时间、工作目录、命令行参数等。 2. **获取图标信息**:LNK文件通常包含目标程序的图标,该库可以提取这些...

    VISTA与W indow的LNK文件的打开方式更改其他文件的修复方法

    LNK文件是Windows系统中用于创建应用程序、文件或文件夹快捷方式的一种特殊文件格式。当用户修改了LNK文件的默认打开方式时,实际上就是更改了该文件类型的关联应用程序。这种情况下,原本应该由Windows资源管理器...

    获取LNK文件的源目标路径的软件源码

    2. **链接解析**:要获取LNK文件的目标路径,你需要使用`Shell.Application`对象,它可以解析快捷方式文件。首先,创建一个`Shell.Application`实例,然后使用`NameSpace`方法打开LNK文件所在的文件夹,再用`Items`...

    windows快捷方式解析.zip

    `lnk-parser`是这个项目的核心,它是一个用于解析.lnk文件的类或者库。可能包含以下功能: 1. **读取.lnk文件**:能够读取快捷方式文件的内容,并提取出头信息、链路信息、图标信息等。 2. **解析目标路径**:从....

    [MS-SHLLINK]Shell Link(.LNK) Binary File Format

    这些信息对于解析LNK文件至关重要。 2. **链接标识 (Link Identifier)**:记录了源文件的一些基本属性,如文件名、文件大小、创建时间等。 3. **目标列表 (Target List)**:包含了指向目标文件或目录的实际路径信息...

    一份解析windows快捷方式文件格式的代码

    使用VC++来解析.lnk文件,首先需要包含必要的库,如`#include &lt;Windows.h&gt;`,并使用COM接口如`IShellLinkW`和`IPersistFile`。以下是一个简单的步骤概述: 1. 创建`IShellLinkW`实例,并查询`IPersistFile`接口。 2...

    windows快捷方式(lnk文件)格式文档

    此外,LNK文件还可能包含网络路径、相对路径或UNC路径信息,以便在不同环境中正确解析目标。 三、创建与使用 创建LNK文件可以通过右键点击目标文件或程序,然后选择“发送到”-&gt;“桌面(创建快捷方式)”来完成。...

    待解决问题LNK2019 无法解析的外部符号

    在编程过程中,我们时常会遇到各种链接错误,其中"LNK2019: 无法解析的外部符号"是Visual Studio C++编译器中一个常见的错误,这通常发生在链接阶段,意味着编译器找不到在编译时声明但在链接时没有实现的函数或变量...

    lnk文件分析的软件源码

    【标题】"lnk文件分析的软件源码"所涉及的知识点主要集中在Windows操作系统中的快捷方式(lnk)文件解析和VB(VBScript Basic)编程语言的应用上。在Windows系统中,lnk文件是一种特殊的文件类型,它相当于一个指向其他...

    解决error LNK2001 无法解析的外部符号 int __cdecl sprintf(

    在压缩包中的`LNK2001 无法解析的外部符号 int __cdecl sprintf 在“附加依赖项”属性中添加 msvcrt.lib.txt`文件,很可能是提供了一个指导,告诉你如何在你的项目设置中添加`msvcrt.lib`来解决这个问题。按照文件中...

    winlnkparser:Windows LNK文件解析器

    **winlnkparser:Windows LNK文件解析器** 在Windows操作系统中,LNK文件是一种快捷方式文件,通常具有.ico图标和指向其他程序、文件或文件夹的指针。`winlnkparser`是一个Python库,专门用于解析这些LNK文件,以...

    ntdll 32/64 .lib文件及.h文件

    在编译过程中,如果遇到“error LNK2019: 无法解析的外部符号”错误,这意味着编译器找不到某个函数的实现,这里具体是`NtClose`函数。`NtClose`是Windows API中的一个函数,用于关闭一个对象句柄,通常与文件、设备...

    vc报错解决办法 error LNK2019无法解析的外部符号,该符号在函数 中被引用

    在VC++编程环境中,当你遇到"error LNK2019: 无法解析的外部符号"的错误时,这通常意味着编译器在链接阶段找不到某个函数或变量的定义。这个错误是链接器(Linker)发出的,因为它在已编译的对象文件或库中找不到在...

    sscom5.13.1.exe

    5. **协议解析**:部分高级版本的sscom工具可能包含协议解析功能,能自动解析特定格式的通信数据,如ASCII、HEX等,简化分析工作。 6. **触发条件设置**:可以设置特定的触发条件,当串口数据达到预设条件时,工具...

    error LNK1120和error lnk2001

    本文将详细解析两个特定的链接错误:error LNK1120和error LNK2001,这两种错误通常发生在Visual Studio等IDE中。通过了解这些错误的含义和解决方法,我们可以更有效地调试和优化代码。 首先,让我们来看看**error ...

    快捷方式模块.zip易语言项目例子源码下载

    在Windows操作系统中,快捷方式以.LNK文件格式存在。 易语言的“快捷方式模块”可能是实现了创建、读取、修改和删除这些.LNK文件的功能。通过这个模块,开发者可以方便地在自己的程序中添加创建快捷方式的选项,...

    如何解决 error LNK2019 无法解析的外部符号,该符号在函数 中被引用

    错误 LNK2019 是一个常见的链接器错误,在Visual Studio等C++开发环境中经常会遇到。这个错误通常意味着编译器在链接阶段找不到某个函数或变量的定义,即在对象文件或库中没有对应的实现。这通常是由于以下原因引起...

    win-lnk-parser:使用VBS完成的LNK解析器支持特殊字符

    简单的程序包可从.lnk文件(Windows快捷方式)中读取一些元数据信息,并支持特殊字符 先决条件 此软件包仅在Windows上有效,并且您必须具有以下应用程序: $ chcp /? $ cscript /? 用法 $ npm i --save win-lnk-...

    pylnk-开源

    1. **读取.lnk文件**:`pylnk` 可以解析.lnk文件的内容,包括目标文件的路径、工作目录、命令行参数、图标位置以及创建时间等信息。 2. **创建.lnk文件**:使用`pylnk`,开发者可以指定目标文件、工作目录、快捷键...

Global site tag (gtag.js) - Google Analytics