Follow

Pineapple Build Guide

Remember: "Pineapple-mode" is only 1/2 of the functionality of the r00tabaga. This guide shows you how to build that half, by itself.

If you want to re-create a r00tabaga from scratch, you'll need to check out Help! I broke my r00tabaga :(

Inspired by the work of Andy Davies at Pentura Labs with Blue For The Pineapple and Samiux with his TL-MR3020 WiFi Pineapple Made Easy Howto, we set out to do the same thing with a TL-MR3040.

Quick Start

This abbreviated guide is here to centralize support resources, and has been modified only insofar as to remove any unnecessary steps and reference use of the TL-MR3040 throughout the instructions. The full version of this guide can be seen in Pentura Labs' original post, entitled: "Blue For The Pineapple," which uses a TL-WR703N.

To begin, download and flash an appropriate build of OpenWRT for your platform (TL-WR703N, TL-MR11U, TL-MR3040) from here: http://downloads.openwrt.org/attitude_adjustment/12.09/ar71xx/generic/

Preparing USB as / (root)

Format a USB key with two partitions, ext4 and swap, install attitude adjustment squashfs, connect router to the internet (wifi client/eth0), update package lists.

Install:

  • kmod-usb-core
  • kmod-usb-storage
  • kmod-fs-ext4
  • block-mount

Duplicate data

Copy necessary files from flash to the new root partition:
For pivot overlay you can either use an empty new rootfs OR copy the contents of the current overlay (JFFS2) to the new rootfs (assuming the filesystem for the new external rootfs is mounted on /mnt/sda2 (swap=/dev/sda1)):

tar -C /overlay -cvf - . | tar -C /mnt/sda2 -xf -

For pivot root (”only possible as of r26109!”) you must make sure to have a complete root filesystem on the external rootfs device. One possible way to get such a system (assuming the filesystem for the new external rootfs is mounted on /mnt/sda1) is to issue

mkdir -p /tmp/cproot
mount --bind / /tmp/cproot
tar -C /tmp/cproot -cvf - . | tar -C /mnt/sda2 -xf -
sync ; umount /mnt
umount /tmp/cproot

Whole external root (pivot root)

After r26109 you can configure a non-overlay rootfs (called a whole_root extroot because the entire filesystem must be present on device, not only the changes from the SquashFS) using option target / in the config mount section for the rootfs device.

In order to set up such a whole root overlay, refer to the example below.

While option is_rootfs will still work after r25787, the preferred method of configuring the extroot is option target /overlay in the config mount section for the rootfs device in the /etc/config/fstab file.

config mount
option target /
option device /dev/sda2
option fstype ext4
option options rw,sync
option enabled 1
option enabled_fsck 0

Reboot & Install Packages

Reboot!

You can now install whatever you want from opkg, and it all goes on the USB Drive.

For some Wifi Cracking, here’s a bunch of useful package names:

opkg install htop bash nano netcat tar openssh-sftp-client nmap tcpdump aircrack-ng kismet-client
kismet-server nbtscan snort karma samba36-client elinks yafc python php5-cgi uhttpd

At this point you can install any additional packages you may want or need.

Installing the Hak5 Pineapple Code

The following series of instructions were performed from both a Linux and Mac OSX operating system.

Hacking the Upgrade Image

Use binwalk (https://code.google.com/p/binwalk/) to extract information about the FileSystem boundaries contained within the Hak5 Pineapples upgrade binary firmware image upgrade.bin, obtainable from http://www.wifipineapple.com/

Below is sample output from binary-walking the image file:

$ binwalk upgrade.bin
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------
0 0x0 Squashfs filesystem, little endian, version 4.0, compression: size: 5342622 bytes, 1410 inodes, blocksize: 262144 bytes, created: Thu Jul 12 02:09:55 2012
6291456 0x600000 uImage header, header size: 64 bytes, header CRC: 0x6B09056F, created: Thu Jul 12 02:10:00 2012, image size: 890595 bytes, Data Address: 0x80060000, Entry Point: 0x80060000, data CRC: 0xF9DC8F7E, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: MIPS OpenWrt Linux-3.2.14
6291520 0x600040 LZMA compressed data (sig 3), properties: 0x6D, dictionary size: 8388608 bytes, uncompressed size: 2690180 bytes

Use dd to extract the image:

Next we use the native unix tool dd, to carve out the squashFS partition:

$dd if=upgrade.bin of=pineapple.img bs=1 count=5342622
5342622+0 records in
5342622+0 records out
5342622 bytes transferred in 12.967170 secs (412011 bytes/sec)

Using Squashfuse (https://github.com/vasi/squashfuse) or OSXFUse, it is easy to mount the pineapple.img extracted earlier:

mkdir -p /Volumnes/pineapple
squashfuse pineapple.img /Volumes/pineapple/

Extract the (MIPS) karma patched binaries (to save on compliation, and from having to build & patch our own binaries)

$ find /Volumes/pineapple/ -name hostapd
/Volumes/pineapple//lib/wifi/hostapd.sh
/Volumes/pineapple//usr/sbin/hostapd
$ find /Volumes/pineapple/ -name hostapd_cli
/Volumes/pineapple//usr/sbin/hostapd_cli

The copy/ssh these binaries onto the TPLink Openwrt installation.

The Pineapple Web Interface

Open Source Method

As of the last month, Sebkinne has made the Pineapple's Web Interface available as open source via github:

git clone https://github.com/WiFiPineapple/web-interface.git /pineapple

Notes

  • Disable all update modules – as this will break the build, the upgrades/updates are all geared for Alfa AccessPoints so you should go through all the code removing the update/upgrade routines to avoid accidentally bricking the TPLink in the future.
  • Secondly the ps command is slightly different in the version on the TPLink search and replace “ps aux| ps auxww” with ps.
  • From simon: 
    grep -lr -e ‘ps aux’ * | xargs sed -i ‘s/ps aux/ps/g’
    grep -lr -e ‘ps -all’ * | xargs sed -i ‘s/ps -all/ps/g’
    grep -lr -e ‘ps auxww’ * | xargs sed -i ‘s/ps auxww/ps/g’

Configuration Files

To make this build compatible with the existing Pineapple Scripts (eg.http://wifipineapple.com/wp4.sh). You need to replace the exisitng OpenWRT config files with the ones listed below:

/etc/config/dhcp

config dnsmasq
option domainneeded 1
option boguspriv 1
option filterwin2k 0 # enable for dial on demand
option localise_queries 1
option rebind_protection 1 # disable if upstream must serve RFC1918 addresses
option rebind_localhost 1 # enable for RBL checking and similar services
#list rebind_domain example.lan # whitelist RFC1918 responses for domains
option local '/lan/'
option domain 'lan'
option expandhosts 1
option nonegcache 0
option authoritative 1
option readethers 1
option leasefile '/tmp/dhcp.leases'
option resolvfile '/tmp/resolv.conf.auto'

config dhcp lan
option interface lan
option start 100
option limit 150
option leasetime 12h
option 'ignore' '0'
list 'dhcp_option' '3,172.16.42.42'
list 'dhcp_option' '3,172.16.42.1'
list 'dhcp_option' '6,172.16.42.1,8.8.8.8'
list 'dhcp_option' '6,172.16.42.1,208.67.222.222'

/etc/config/firewall

config defaults
option syn_flood 1
option input ACCEPT
option output ACCEPT
option forward REJECT
# Uncomment this line to disable ipv6 rules
# option disable_ipv6 1

config zone
option name lan
option network 'lan'
option input ACCEPT
option output ACCEPT
option forward REJECT

config zone
option name wan
option network 'wan'
option input REJECT
option output ACCEPT
option forward REJECT
option masq 1
option mtu_fix 1

config forwarding
option src lan
option dest wan

# We need to accept udp packets on port 68,
# see https://dev.openwrt.org/ticket/4108
config rule
option src wan
option proto udp
option dest_port 68
option target ACCEPT
option family ipv4

# Allow IPv4 ping
config rule
option src wan
option proto icmp
option icmp_type echo-request
option family ipv4
option target ACCEPT

# Allow essential incoming IPv6 ICMP traffic
config rule
option src wan
option dest *
option proto icmp
list icmp_type echo-request
list icmp_type destination-unreachable
list icmp_type packet-too-big
list icmp_type time-exceeded
list icmp_type bad-header
list icmp_type unknown-header-type
option limit 1000/sec
option family ipv6
option target ACCEPT

# include a file with users custom iptables rules
config include
option path /etc/firewall.user

/etc/config/network

config interface 'loopback'
option ifname 'lo'
option proto 'static'
option ipaddr '127.0.0.1'
option netmask '255.0.0.0'

config interface 'lan'
option ifname 'eth0'
option type 'bridge'
option proto 'static'
option ipaddr '172.16.42.1'
option netmask '255.255.255.0'
option gateway '172.16.42.42'
option dns '8.8.8.8'

config interface 'wan'
option ifname 'wlan0'
option proto 'dhcp'

/etc/config/uhttpd

# Server configuration
config uhttpd main

option 'index_page' 'index.php'
option 'error_page' '/index.php'
# HTTP listen addresses, multiple allowed
list listen_http 0.0.0.0:80
# list listen_http [::]:80

# HTTPS listen addresses, multiple allowed
list listen_https 0.0.0.0:443
# list listen_https [::]:443

# Server document root
option home /www

# Reject requests from RFC1918 IP addresses
# directed to the servers public IP(s).
# This is a DNS rebinding countermeasure.
option rfc1918_filter 1

# Certificate and private key for HTTPS.
# If no listen_https addresses are given,
# the key options are ignored.
option cert /etc/uhttpd.crt
option key /etc/uhttpd.key

# CGI url prefix, will be searched in docroot.
# Default is /cgi-bin
option cgi_prefix /cgi-bin

# List of extension->interpreter mappings.
# Files with an associated interpreter can
# be called outside of the CGI prefix and do
# not need to be executable.
list interpreter ".php=/usr/bin/php-cgi"
# list interpreter ".cgi=/usr/bin/perl"
# Lua url prefix and handler script.
# Lua support is disabled if no prefix given.
# option lua_prefix /luci
# option lua_handler /usr/lib/lua/luci/sgi/uhttpd.lua

# CGI/Lua timeout, if the called script does not
# write data within the given amount of seconds,
# the server will terminate the request with
# 504 Gateway Timeout response.
option script_timeout 60

# Network timeout, if the current connection is
# blocked for the specified amount of seconds,
# the server will terminate the associated
# request process.
option network_timeout 30

# TCP Keep-Alive, send periodic keep-alive probes
# over established connections to detect dead peers.
# The value is given in seconds to specify the
# interval between subsequent probes.
# Setting this to 0 will disable TCP keep-alive.
option tcp_keepalive 1

# Basic auth realm, defaults to local hostname
# option realm OpenWrt

# Certificate defaults for px5g key generator
config cert px5g

# Validity time
option days 730

# RSA key size
option bits 1024

# Location
option country DE
option state Berlin
option location Berlin

# Common name
option commonname OpenWrt

config uhttpd pineapple
list listen_http 0.0.0.0:1471
option home /pineapple
option index_page index.php
option 'error_page' '/index.php'

# Configuration file in busybox httpd format
option config /etc/config/httpd.conf
option rfc1918_filter 1

# Certificate and private key for HTTPS.
# If no listen_https addresses are given,
# the key options are ignored.
option cert /etc/uhttpd.crt
option key /etc/uhttpd.key

# CGI url prefix, will be searched in docroot.
# Default is /cgi-bin
option cgi_prefix /cgi-bin

# List of extension->interpreter mappings.
# Files with an associated interpreter can
# be called outside of the CGI prefix and do
# not need to be executable.
list interpreter ".php=/usr/bin/php-cgi"

# CGI/Lua timeout, if the called script does not
# write data within the given amount of seconds,
# the server will terminate the request with
# 504 Gateway Timeout response.
option script_timeout 60

# Network timeout, if the current connection is
# blocked for the specified amount of seconds,
# the server will terminate the associated
# request process.
option network_timeout 30# TCP Keep-Alive, send periodic keep-alive probes
# over established connections to detect dead peers.
# The value is given in seconds to specify the
# interval between subsequent probes.
# Setting this to 0 will disable TCP keep-alive.
option tcp_keepalive 1

/etc/php.ini

[PHP]

zend.ze1_compatibility_mode = Off

; Language Options

engine = On
short_open_tag = On
precision    =  12
y2k_compliance = On
output_buffering = Off
;output_handler =
zlib.output_compression = Off
;zlib.output_compression_level = -1
;zlib.output_handler =
implicit_flush = Off
unserialize_callback_func =
serialize_precision = 100

;open_basedir =
disable_functions =
disable_classes =

; Colors for Syntax Highlighting mode.  Anything that's acceptable in
;  would work.
;highlight.string  = #DD0000
;highlight.comment = #FF9900
;highlight.keyword = #007700
;highlight.bg      = #FFFFFF
;highlight.default = #0000BB
;highlight.html    = #000000

;ignore_user_abort = On
;realpath_cache_size = 16k
;realpath_cache_ttl = 120

; Miscellaneous

expose_php = On

; Resource Limits

max_execution_time = 30	; Maximum execution time of each script, in seconds.
max_input_time = 60	; Maximum amount of time each script may spend parsing request data.
;max_input_nesting_level = 64
memory_limit = 8M	; Maximum amount of memory a script may consume.

; Error handling and logging

; Error Level Constants:
; E_ALL             - All errors and warnings (includes E_STRICT as of PHP 6.0.0)
; E_ERROR           - fatal run-time errors
; E_RECOVERABLE_ERROR  - almost fatal run-time errors
; E_WARNING         - run-time warnings (non-fatal errors)
; E_PARSE           - compile-time parse errors
; E_NOTICE          - run-time notices (these are warnings which often result
;                     from a bug in your code, but it's possible that it was
;                     intentional (e.g., using an uninitialized variable and
;                     relying on the fact it's automatically initialized to an
;                     empty string)
; E_STRICT			- run-time notices, enable to have PHP suggest changes
;                     to your code which will ensure the best interoperability
;                     and forward compatibility of your code
; E_CORE_ERROR      - fatal errors that occur during PHP's initial startup
; E_CORE_WARNING    - warnings (non-fatal errors) that occur during PHP's
;                     initial startup
; E_COMPILE_ERROR   - fatal compile-time errors
; E_COMPILE_WARNING - compile-time warnings (non-fatal errors)
; E_USER_ERROR      - user-generated error message
; E_USER_WARNING    - user-generated warning message
; E_USER_NOTICE     - user-generated notice message
; E_DEPRECATED      - warn about code that will not work in future versions
;                     of PHP
; E_USER_DEPRECATED - user-generated deprecation warnings
;
; Common Values:
;   E_ALL & ~E_NOTICE  (Show all errors, except for notices and coding standards warnings.)
;   E_ALL & ~E_NOTICE | E_STRICT  (Show all errors, except for notices)
;   E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR  (Show only errors)
;   E_ALL | E_STRICT  (Show all errors, warnings and notices including coding standards.)
; Default Value: E_ALL & ~E_NOTICE
error_reporting  =  E_ALL & ~E_NOTICE & ~E_STRICT

display_errors = On
display_startup_errors = Off
log_errors = Off
log_errors_max_len = 1024
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On
;report_zend_debug = 0
track_errors = Off
;html_errors = Off
;docref_root = "/phpmanual/"
;docref_ext = .html
;error_prepend_string = ""
;error_append_string = ""
; Log errors to specified file.
;error_log = /var/log/php_errors.log
; Log errors to syslog.
;error_log = syslog

; Data Handling

;arg_separator.output = "&"
;arg_separator.input = ";&"
variables_order = "EGPCS"
request_order = "GP"
register_globals = Off
register_long_arrays = Off
register_argc_argv = On
auto_globals_jit = On
post_max_size = 8M
;magic_quotes_gpc = Off
magic_quotes_runtime = Off
magic_quotes_sybase = Off
auto_prepend_file =
auto_append_file =
default_mimetype = "text/html"
;default_charset = "iso-8859-1"
;always_populate_raw_post_data = On

; Paths and Directories

; UNIX: "/path1:/path2"
;include_path = ".:/php/includes"
doc_root = ""
user_dir =
extension_dir = "/usr/lib/php"
enable_dl = On
;cgi.force_redirect = 1
;cgi.nph = 1
;cgi.redirect_status_env = ;
cgi.fix_pathinfo=1
;fastcgi.impersonate = 1;
;fastcgi.logging = 0
;cgi.rfc2616_headers = 0

; File Uploads

file_uploads = On
upload_tmp_dir = "/tmp"
upload_max_filesize = 2M
max_file_uploads = 20

; Fopen wrappers

allow_url_fopen = On
allow_url_include = Off
;from="john@doe.com"
;user_agent="PHP"
default_socket_timeout = 60
;auto_detect_line_endings = Off

; Dynamic Extensions

;extension=ctype.so
;extension=curl.so
;extension=dom.so
;extension=exif.so
;extension=ftp.so
;extension=gd.so
;extension=gmp.so
;extension=hash.so
;extension=iconv.so
;extension=json.so
;extension=ldap.so
;extension=mbstring.so
;extension=mcrypt.so
;extension=mysql.so
;extension=openssl.so
;extension=pcre.so
;extension=pdo.so
;extension=pdo-mysql.so
;extension=pdo-pgsql.so
;extension=pdo_sqlite.so
;extension=pgsql.so
;extension=session.so
;extension=soap.so
;extension=sockets.so
;extension=sqlite.so
;extension=sqlite3.so
;extension=tokenizer.so
;extension=xml.so
;extension=xmlreader.so
;extension=xmlwriter.so

; Module Settings

[APC]
apc.enabled = 1
apc.shm_segments = 1	;The number of shared memory segments to allocate for the compiler cache.
apc.shm_size = 4M	;The size of each shared memory segment.

[Date]
;date.timezone =
;date.default_latitude = 31.7667
;date.default_longitude = 35.2333
;date.sunrise_zenith = 90.583333
;date.sunset_zenith = 90.583333

[filter]
;filter.default = unsafe_raw
;filter.default_flags =

[iconv]
;iconv.input_encoding = ISO-8859-1
;iconv.internal_encoding = ISO-8859-1
;iconv.output_encoding = ISO-8859-1

[sqlite]
;sqlite.assoc_case = 0

[sqlite3]
;sqlite3.extension_dir =

[Pdo_mysql]
pdo_mysql.cache_size = 2000
pdo_mysql.default_socket=

[MySQL]
mysql.allow_local_infile = On
mysql.allow_persistent = On
mysql.cache_size = 2000
mysql.max_persistent = -1
mysql.max_links = -1
mysql.default_port =
mysql.default_socket =
mysql.default_host =
mysql.default_user =
mysql.default_password =
mysql.connect_timeout = 60
mysql.trace_mode = Off

[PostgresSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0

[Session]
session.save_handler = files
session.save_path = "/tmp"
session.use_cookies = 1
;session.cookie_secure =
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor     = 100
session.gc_maxlifetime = 1440
session.bug_compat_42 = On
session.bug_compat_warn = On
session.referer_check =
session.entropy_length = 0
;session.entropy_file = /dev/urandom
session.entropy_file =
;session.entropy_length = 16
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.hash_function = 0
session.hash_bits_per_character = 4
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=,fieldset="

[mbstring]
;mbstring.language = Japanese
;mbstring.internal_encoding = EUC-JP
;mbstring.http_input = auto
;mbstring.http_output = SJIS
;mbstring.encoding_translation = Off
;mbstring.detect_order = auto
;mbstring.substitute_character = none;
;mbstring.func_overload = 0
;mbstring.strict_detection = Off
;mbstring.http_output_conv_mimetype=
;mbstring.script_encoding=

[gd]
;gd.jpeg_ignore_warning = 0

[exif]
;exif.encode_unicode = ISO-8859-15
;exif.decode_unicode_motorola = UCS-2BE
;exif.decode_unicode_intel    = UCS-2LE
;exif.encode_jis =
;exif.decode_jis_motorola = JIS
;exif.decode_jis_intel    = JIS

[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5

[sysvshm]
;sysvshm.init_mem = 10000

[ldap]
ldap.max_links = -1

[mcrypt]
;mcrypt.algorithms_dir=
;mcrypt.modes_dir=

 And that's it! With these configs in place, you're TP-Link TL-MR3040 will now look and taste just like a pineapple!

Was this article helpful?
1 out of 1 found this helpful
Have more questions? Submit a request

4 Comments

Article is closed for comments.
Powered by Zendesk