SRI International |
|
Conficker C Active P2P Scanner |
|
Computer
Science Laboratory SRI International 333 Ravenswood Avenue Menlo Park CA 94025 USA |
Download
Version 0.1B: Conficker_C_P2P_Scanner.Cauthor: Vinod Yegneswaran
compiled and tested on - Gnu gcc ver 4.2.2, running Linux, little endian only.
Acknowledgements: thanks to Fabien Perigaud - CERT Lexsi, France
README
Conficker_C_P2P_Scanner is an network-based active scanner application that scans a subnet for Conficker C infected hosts.Usage:
Conficker_C_P2P_Scanner [-t ms waittime] [-v (verbose)] <low-address> <high-address>
low|high-address - specifies the start and end address ranges to be scanned
ex: % Conficker_C_P2P_Scanner 192.168.7.0 192.168.99.255
will scan all addresses in subnets 192.168.[7-99]
Detection Synopsis:
All Conficker C hosts perform outbound P2P scanning in search of other C infected peers. Each C-infected host opens four network ports in listen mode: 2 TCP ports and 2 UDP. These four listen ports are derived from a function of the host's own IP address and the current epoch week. To illustrate the algorithm used to compute C's P2P client listen ports, we include a source code example C implementation, which we reverse-engineered from a Conficker C binary captured on 5 March 2009.Conficker_C_P2P_Scanner will scan the low-thru-high address range in search of IP addresses that have established TCP listen ports on their associated Conficker C P2P listen ports. An alarm is provided each time a host is found to be listening on its P2P listen port.
Good Luck.
SRI International
Example Conficker C P2P Port Generation Algorithm
/* Copyright: SRI Internationalauthors: Hassen Saidi, Vinod Yegneswaran, and Drew Dean, 31 March 2009.
Acknowledgments: thanks to David Fifield from Bam Software for identifying
the purpose of portBlacklist.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
typedef union {
int16_t s16[8];
uint16_t u16[8];
int32_t s32[4];
} result_t;
typedef union {
int64_t s64;
int32_t s32[2];
uint32_t u32[2];
int16_t s16[4];
} var_t;
uint32_t portBlacklist[64] =
{
0xffffffff, 0xffffffff,
0xf3977011,
0x1e2282df,
0x01600002,
0x000000a1,
0x00000080,
0x00000180,
0x00000280,
0x00100040,
0x10000008,
0x00000002,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
};
#define IS_PORT_BLACKLISTED(x) (1 << ((x >> 5) & 0x1F)) & portBlacklist[x >> 10]
/* NB: the portgen() function below is endian-dependent, and reverse-engineered
for a little-endian (e.g. x86, VAX, Alpha, etc.) machine. Changes will be
required for the array offsets in the unions to run on a big-endian (e.g. most
SPARC, Power(PC), MIPS, etc.) machine. Other than the endian issue, this
implementaiton should be portable. */
int portgen(int ip, result_t *res, int week)
{
var_t v;
int64_t KONST = 0x15A4E35;
int i;
memset(res, 0, sizeof(result_t));
v.s32[0] = ~ip;
/* Generate fixed ports */
do {
do {
v.s64 = KONST * v.u32[0] + 1;
res->s16[0] ^= v.s16[2];
for (i=1; i < 10; i++) {
}
} while (IS_PORT_BLACKLISTED(res->s32[0]));
} while (IS_PORT_BLACKLISTED(res->s32[1]) || res->s32[0] == res->s32[1]);
v.s32[0] = week ^ v.s64;
/* Generate week-dependent ports */
do {
do {
v.s64 = KONST * v.u32[0] + 1;
res->s16[4] ^= v.s16[2];
for (i=1; i < 10; i++) {
}
} while (IS_PORT_BLACKLISTED(res->s32[2]));
} while (IS_PORT_BLACKLISTED(res->s32[3]) || res->s32[2] == res->s32[3] ||
return v.s64;
}
int main(int argc, char** argv) {
int a1,a3;
result_t res;
int i, rc;
if (argc != 3) {
printf("usage: conficker_ports <ip addr> <epoch week>\n");
exit(0);
}
a1 = inet_addr(argv[1]);
a3 = atoi(argv[2]);
rc=portgen(a1, &res, a3);
printf("ports are TCP (fixed), UDP (fixed), TCP (week-dependent), UDP
(week-dependent)\n");
for (i=0;i<8;i++) {
if (res.u16[i])
printf("%d\t", res.u16[i]);
}
printf("\n");
return 0;
}
Acknowledgments
We gratefully thank the National Science Foundation (NSF) and the Army Research Office (ARO) for their sponsorship of this research activity.