Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,6 @@ group :test do
gem 'timecop'
end


gem "rqrcode", "~> 3.1"
gem "chunky_png", "~> 1.4"
6 changes: 6 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,10 @@ GEM
forwardable
ipaddr
rkelly-remix (0.0.7)
rqrcode (3.1.0)
chunky_png (~> 1.0)
rqrcode_core (~> 2.0)
rqrcode_core (2.0.0)
rspec (3.13.1)
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
Expand Down Expand Up @@ -669,6 +673,7 @@ PLATFORMS

DEPENDENCIES
allure-rspec
chunky_png (~> 1.4)
debug (>= 1.0.0)
factory_bot_rails
fivemat
Expand All @@ -679,6 +684,7 @@ DEPENDENCIES
pry-byebug
rake
redcarpet
rqrcode (~> 3.1)
rspec-rails
rspec-rerun
rubocop (= 1.75.7)
Expand Down
252 changes: 252 additions & 0 deletions modules/auxiliary/generator/android_deeplink.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
require 'msf/core'

class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::FILEFORMAT

# How to use this module:
#
# Search: `search android_deeplink` to check for module
# 1. Load the module:
# 2. Set the deep link scheme (like for Wechat lets say):
# `use auxiliary/generator/android_deeplink`
#
# `set DEEPLINK_SCHEME weixin://`
#
# 3. Set the deep link path :
# `set DEEPLINK_PATH dl/scanqr?type=qr `
#
# 4. Specify the output filename for the generated QR code:
# `set FILENAME wechat_qr.png`
#
# 5. Run the module to generate the QR code:
# `run`

def initialize(info = {})
super(update_info(info,
'Name' => 'Android Deep Link QR Code Payload Generator',
'Description' => %q{
This module make QR code with Android Deep Link.
When user scan QR, phone open app with deep link.
Can use for test app security or social engineering.
},
'Author' => [ 'ctkqiang' ],
'License' => MSF_LICENSE
))

register_options([
OptEnum.new('DEEPLINK_SCHEME', [true, 'Choose deep link scheme', 'weixin://', [
'weixin://',
'grab://',
'boost://',
'alipay://',
'fb://',
'instagram://',
'twitter://',
'line://',
'telegram://',
'whatsapp://',
'tiktok://',
'shopee://',
'lazada://',
'gpay://',
'applepay://',
'youtube://',
'spotify://',
'linkedin://',
'pinterest://',
'snapchat://',
'paypal://',
'skype://',
'discord://',
'slack://',
'zoomus://',
'meet://',
'waze://',
'maps://',
'uber://',
'lyft://',
'cameraplus://',
'vimeo://',
'tumblr://',
'reddit://',
'hulu://',
'netflix://',
'soundcloud://',
'deezer://',
'tidal://',
'messenger://',
'fb-messenger://',
'skype-for-business://',
'teams://',
'onedrive://',
'dropbox://',
'box://',
'zoom://',
'twitch://',
'quora://',
'medium://',
'goodreads://',
'yelp://',
'tripadvisor://',
'booking://',
'airbnb://',
'grabpay://',
'wechatpay://',
'ocbc://',
'maybank2u://',
'rhb://',
'cimb://',
'dbs://',
'hsbc://',
'standardchartered://',
'custom://'
]]),
OptString.new('CUSTOM_SCHEME', [false, 'If choose custom, put scheme here', 'myapp://']),
OptString.new('DEEPLINK_PATH', [false, 'Deep link path and parameters', 'pay?amount=100']),
OptString.new('FILENAME', [true, 'QR code output file', 'deeplink_qr.png']),
OptInt.new('SIZE', [true, 'QR code size in pixel', 400])
])
end

def run

begin
require 'rqrcode'
require 'chunky_png'
gems_available = true
rescue LoadError
gems_available = false
end

unless gems_available
print_error("Required gems not found. Please install them with:")
print_error("gem install rqrcode chunky_png")
print_error("Then restart msfconsole and try again.")
return
end

scheme = datastore['DEEPLINK_SCHEME']

if scheme == 'custom://'
custom_scheme = datastore['CUSTOM_SCHEME']
if custom_scheme.empty?
print_error("Please set CUSTOM_SCHEME option")
return
end

scheme = custom_scheme
end

path = datastore['DEEPLINK_PATH'] || ""

if path.empty?
target_deep_link = scheme
else
if path.start_with?('/')
target_deep_link = scheme + path
else
target_deep_link = scheme + '/' + path
end
end

print_status("Start generate QR code for deep link...")
print_status("Deep Link: #{target_deep_link}")

app_name = get_app_name(scheme)

print_status("This deep link will open: #{app_name}")

begin
generate_qr_code(target_deep_link)
print_good("QR code generate success: #{datastore['FILENAME']}")
print_warning("When user scan this QR, #{app_name} will open with deep link")

rescue => e
print_error("Generate QR code fail: #{e.message}")
end
end

private

def generate_qr_code(url)
qrcode = RQRCode::QRCode.new(url)

png = qrcode.as_png(
size: datastore['SIZE'],
border_modules: 1,
module_px_size: 6,
fill: 'white',
color: 'black'
)

File.binwrite(datastore['FILENAME'], png.to_s)
end

def get_app_name(scheme)
case scheme
when 'weixin://' then 'WeChat'
when 'grab://' then 'Grab'
when 'boost://' then 'Boost'
when 'alipay://' then 'Alipay'
when 'fb://' then 'Facebook'
when 'instagram://' then 'Instagram'
when 'twitter://' then 'Twitter'
when 'line://' then 'LINE'
when 'telegram://' then 'Telegram'
when 'whatsapp://' then 'WhatsApp'
when 'tiktok://' then 'TikTok'
when 'shopee://' then 'Shopee'
when 'lazada://' then 'Lazada'
when 'gpay://' then 'Google Pay'
when 'applepay://' then 'Apple Pay'
when 'youtube://' then 'YouTube'
when 'spotify://' then 'Spotify'
when 'linkedin://' then 'LinkedIn'
when 'pinterest://' then 'Pinterest'
when 'snapchat://' then 'Snapchat'
when 'paypal://' then 'PayPal'
when 'skype://' then 'Skype'
when 'discord://' then 'Discord'
when 'slack://' then 'Slack'
when 'zoomus://', 'zoom://' then 'Zoom'
when 'meet://' then 'Google Meet'
when 'waze://' then 'Waze'
when 'maps://' then 'Maps'
when 'uber://' then 'Uber'
when 'lyft://' then 'Lyft'
when 'cameraplus://' then 'Camera+'
when 'vimeo://' then 'Vimeo'
when 'tumblr://' then 'Tumblr'
when 'reddit://' then 'Reddit'
when 'hulu://' then 'Hulu'
when 'netflix://' then 'Netflix'
when 'soundcloud://' then 'SoundCloud'
when 'deezer://' then 'Deezer'
when 'tidal://' then 'Tidal'
when 'messenger://', 'fb-messenger://' then 'Messenger'
when 'skype-for-business://' then 'Skype for Business'
when 'teams://' then 'Microsoft Teams'
when 'onedrive://' then 'OneDrive'
when 'dropbox://' then 'Dropbox'
when 'box://' then 'Box'
when 'twitch://' then 'Twitch'
when 'quora://' then 'Quora'
when 'medium://' then 'Medium'
when 'goodreads://' then 'Goodreads'
when 'yelp://' then 'Yelp'
when 'tripadvisor://' then 'Tripadvisor'
when 'booking://' then 'Booking.com'
when 'airbnb://' then 'Airbnb'
when 'grabpay://' then 'GrabPay'
when 'wechatpay://' then 'WeChat Pay'
when 'ocbc://' then 'OCBC Bank'
when 'maybank2u://' then 'Maybank2u'
when 'rhb://' then 'RHB Bank'
when 'cimb://' then 'CIMB Bank'
when 'dbs://' then 'DBS Bank'
when 'hsbc://' then 'HSBC'
when 'standardchartered://' then 'Standard Chartered'
else 'Unknown App'
end
end
end