diff --git a/board/bpreader.c b/board/bpreader.c index 59cdcf6..908d932 100644 --- a/board/bpreader.c +++ b/board/bpreader.c @@ -15,6 +15,7 @@ static HRESULT bp_handle_irp(struct irp *irp); static HRESULT bp_handle_irp_locked(struct irp *irp); +static HRESULT crack_bpreader_request(); static struct bpreader_config *config; static struct uart bp_uart; @@ -22,7 +23,7 @@ static CRITICAL_SECTION bp_lock; static uint8_t bp_written_bytes[520]; static uint8_t bp_readable_bytes[520]; static uint8_t last_cmd = 0; -static uint16_t write_ct = 0; +static uint16_t read_ct = 0; HRESULT bpreader_init(struct bpreader_config *cfg, uint16_t port) { @@ -90,38 +91,37 @@ static HRESULT bp_handle_irp_locked(struct irp *irp) if (FAILED(hr)) { return hr; } + #if 0 if (irp->op == IRP_OP_WRITE) { dprintf("WRITE:\n"); dump_iobuf(&bp_uart.written); } #endif + if (irp->op == IRP_OP_WRITE) { - write_ct = 0; + read_ct = 0; if (bp_uart.written.bytes[0] == 0x55) { dprintf("Reader: Hello\n"); - return hr; + bp_uart.written.pos = 0; // consume the written buffer } else if (bp_uart.written.bytes[3] == 0x00) { - dprintf("Reader: Wait Next Cmd\n"); - last_cmd = 0x00; - return hr; - } - else { - last_cmd = bp_uart.written.bytes[3]; - dprintf("Reader: Wrote Cmd %X\n", last_cmd); - return hr; + bp_uart.written.pos = 0; // consume the written buffer } + return hr; } - if (irp->op == IRP_OP_READ) { - dprintf("Reader: last_cmd %02X write_ct %d\n", last_cmd, write_ct); - switch (last_cmd) { + else if (irp->op == IRP_OP_READ) { + if (!read_ct) { + dump_iobuf(&bp_uart.written); + hr = crack_bpreader_request(); + } + switch (bp_uart.written.bytes[3]) { case 0x02: - dprintf("Reader: Unknown 0x02\n"); - if (!write_ct) { - uint8_t buff[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, - 0xfb, 0xd5, 0x0d, 0x00, 0x06, 0x00, 0x18, 0x00 }; + if (!read_ct) { + dprintf("Reader: Unknown 0x02\n"); + uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x05, + 0xFB, 0xD5, 0x0D, 0x00, 0x06, 0x00, 0x18, 0x00 }; hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff)); } @@ -129,9 +129,9 @@ static HRESULT bp_handle_irp_locked(struct irp *irp) break; case 0x03: - if (!write_ct) { - dprintf("Reader: Initalize Reader\n"); - uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x02, + if (!read_ct) { + dprintf("Reader: Unknown 0x03\n"); + uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x02, 0xFE, 0xD5, 0x19, 0x12, 0x00 }; hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff)); } @@ -139,16 +139,25 @@ static HRESULT bp_handle_irp_locked(struct irp *irp) break; case 0x04: - case 0x06: - if (!write_ct && bp_uart.written.bytes[6] == 0x0e && last_cmd == 0x04) { + if (!read_ct && bp_uart.written.bytes[6] == 0x0E && last_cmd == 0x04) { dprintf("Reader: Unknown second 0x04\n"); - uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x02, + uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x02, 0xFE, 0xD5, 0x0F, 0x1C, 0x00 }; hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff)); } - else if (!write_ct) { - dprintf("Reader: Unknown 0x06/0x04\n"); - uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x02, + else if (!read_ct) { + dprintf("Reader: Unknown 0x04\n"); + uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x02, + 0xFE, 0xD5, 0x33, 0xF8, 0x00 }; + hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff)); + } + bp_uart.written.pos = 0; + break; + + case 0x06: + if (!read_ct) { + dprintf("Reader: Unknown 0x06\n"); + uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x02, 0xFE, 0xD5, 0x33, 0xF8, 0x00 }; hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff)); } @@ -156,31 +165,97 @@ static HRESULT bp_handle_irp_locked(struct irp *irp) break; case 0x05: - if (!write_ct) { + if (!read_ct) { dprintf("Reader: Unknown 0x05\n"); - uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x03, + uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x03, 0xFD, 0xD5, 0x09, 0x00, 0x22, 0x00 }; hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff)); } bp_uart.written.pos = 0; break; + + case 0x09: + if (!read_ct) { + dprintf("Reader: Poll card\n"); + uint8_t buff[37] = {}; + if (GetAsyncKeyState(VK_RETURN) & 0x8000) { + dprintf("Reader: Touch card %ls\n", config->access_code); + uint8_t buff2[] = { + 0x00, 0x00, 0xFF, 0x18, 0xE8, 0xD5, 0x4B, 0x01, 0x01, 0x14, 0x01, // Data + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IDm + 0x00, 0xF1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, // PMm + 0x88, 0xB4, // System Code + 0x00, 0x00 }; + /*uint8_t buff2[] = { + 0x00, 0x00, 0xFF, 0x0C, 0xF4, 0xD5, 0x4B, 0x01, 0x01, + 0x00, 0x04, // ATQA + 0x08, //SAK + 0x04, // Unknown + 0x42, 0xF0, 0xE7, 0x05, // S/N + 0xB0, 0x00 }; // Footer*/ + memcpy_s(buff, sizeof(buff), buff2, sizeof(buff2)); + } else { + uint8_t buff2[] = { 0x00, 0x00, 0xFF, 0x03, 0xFD, 0xD5, 0x4B, 0x00, 0xE0, 0x00 }; + memcpy_s(buff, sizeof(buff), buff2, sizeof(buff2)); + } + + hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff)); + } + bp_uart.written.pos = 0; + break; + + case 0x0E: + if (!read_ct) { + dprintf("Reader: Unknown 0x0E\n"); + uint8_t buff[] = { 0x00, 0x00, 0xff, 0x02, + 0xfe, 0xd5, 0x33, 0xf8, 0x00 }; + hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff)); + } + bp_uart.written.pos = 0; + break; case 0x12: - if (!write_ct) { + if (!read_ct) { dprintf("Reader: Unknown 0x12\n"); - uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x0a, + uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x0a, 0xf6, 0xd5, 0x07, 0xff, 0x3f, 0x0e, 0xf1, 0xff, 0x3f, 0x0e, 0xf1, 0xaa, 0x00 }; hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff)); } bp_uart.written.pos = 0; break; + + case 0x14: + if (!read_ct) { + dprintf("Reader: Unknown 0x14\n"); + uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x20, 0xE0, 0xD5, 0xA1, + 0x00, 0x1D, 0x07, // Unknown + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IDm + 0x00, 0x00, 0x01, // Unknown + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IDm + 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00 }; + hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff)); + } + bp_uart.written.pos = 0; + break; + + case 0x18: + if (!read_ct) { + dprintf("Reader: Unknown 0x18\n"); + uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x0D, + 0xF3, 0xD5, 0x07, 0xDC, 0xF4, 0x3F, 0x11, 0x4D, 0x85, 0x61, 0xF1, 0x26, + 0x6A, 0x87, 0xC9, 0x00 }; + hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff)); + } + bp_uart.written.pos = 0; + break; default: dprintf("Reader: Unknown Command %02X\n", last_cmd); dump_iobuf(&bp_uart.written); break; } - write_ct++; + read_ct++; } if (FAILED(hr)) { @@ -196,4 +271,62 @@ static HRESULT bp_handle_irp_locked(struct irp *irp) bp_uart.written.pos = 0; // consume the written buffer return hr; +} + +static HRESULT crack_bpreader_request() { + struct bpreader_cmd_header header = { bp_uart.written.bytes[0], bp_uart.written.bytes[1], bp_uart.written.bytes[2], + bp_uart.written.bytes[3], bp_uart.written.bytes[4], bp_uart.written.bytes[5], bp_uart.written.bytes[6], + }; + + assert(header.padding0_00 == 0); + assert(header.padding1_00 == 0); + assert(header.padding2_ff == 0xFF); + assert(header.d_identifier == 0xD4); + + switch(header.cmd) { + case 0x06: + dprintf("Reader: Cmd 0x06\n"); + break; + + case 0x08: + dprintf("Reader: Cmd 0x08\n"); + break; + + case 0x12: + dprintf("Reader: Cmd 0x12\n"); + break; + + case 0x18: + dprintf("Reader: Initialize\n"); + break; + + case 0x0C: + dprintf("Reader: Cmd 0x0C\n"); + break; + + case 0x0E: + dprintf("Reader: Set Output\n"); + break; + + case 0x32: + dprintf("Reader: Cmd 0x32\n"); + break; + + case 0x40: + dprintf("Reader: Read Banapass\n"); // 01 03 00 -> Chip ID; 01 30 01 -> Thing after chip ID; 01 60 30 -> send key a + break; + + case 0x4A: + dprintf("Reader: Poll Card\n"); // 01 01 00 ff ff 01 00 -> Felica; 01 00 -> Banapass + break; + + case 0xA0: + dprintf("Reader: Read Felica\n"); + break; + + default: + dprintf("Reader: Unknown command 0x%02x\n", header.cmd); + } + + return S_OK; } \ No newline at end of file diff --git a/board/bpreader.h b/board/bpreader.h index 419f5bd..69f17c8 100644 --- a/board/bpreader.h +++ b/board/bpreader.h @@ -10,4 +10,84 @@ struct bpreader_config { }; HRESULT bpreader_init(struct bpreader_config *cfg, uint16_t port); -void bpreader_congif_load(struct bpreader_config *cfg, const wchar_t *filename); \ No newline at end of file +void bpreader_congif_load(struct bpreader_config *cfg, const wchar_t *filename); + +/* +bpreader packet format WIP +n = final offset +| Offset | Meaning | +|--------|--------------------------------------------------------------------| +| 0 | Always 00 | +| 1 | Always 00 | +| 2 | Always FF | Header +| 3 | len(Data), 0 means no data | +| 4 | FF - ((sum of header bytes) & FF) if data is present | +|--------|--------------------------------------------------------------------| +| 5 | Always D5 (resp) or D4 (req) if data is present, identifier? | +| 6 | Command if data is present | Data +| 7..n-2 | Data if data is present | +|--------|--------------------------------------------------------------------| +| n-1 | FF - ((sum of head + data bytes) & FF) if data is present, else FF | Footer +| n | Always 00 | + +Commands +| Command | Response | Meaning | Response Data (not including leading 0xD5) | +|---------|----------|----------------------------------------------------|------------------------------------------------------------------------| +| 0x00 | 0x00 | Wait Next Command | None | +| 0x02 | 0x05 | Unknown | 0x0D, 0x00, 0x06, 0x00 | +| 0x03 | 0x02 | Unknown, first command and then sent randomly | 0x19 | +| 0x04 | 0x02 | Unknown, only command seen to change it's req data | 0x0F/0x33 | +| 0x05 | 0x03 | Unknown | 0x09, 0x00 | +| 0x06 | 0x02 | Unknown | 0x0F | +| 0x09 | 0x18 | Poll for card | 0x4B, 0x01, 0x01, 0x14, 0x01, [IDm], [PMm], [Sys Code] | +| 0x0E | 0x02 | Unknown | 0x33 | +| 0x12 | 0x0A | Unknown | 0x07, 0xFF, 0x3F, 0x0E, 0xF1, 0xFF, 0x3F, 0x0E, 0xF1 | +| 0x14 | 0x20 | Unknown | a lot, see bpreader.c | +| 0x18 | 0x0D | Unknown | 0x07, 0xDC, 0xF4, 0x3F, 0x11, 0x4D, 0x85, 0x61, 0xF1, 0x26, 0x6A, 0x87 | +*/ +//const uint8_t bpreader_CMD_GO_NEXT[6] = { 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00 }; + +struct bpreader_cmd_header { + uint8_t padding0_00; + uint8_t padding1_00; + uint8_t padding2_ff; + uint8_t data_len; + uint8_t header_checksum; + uint8_t d_identifier; + uint8_t cmd; +}; + +struct bpreader_cmd_footer { + uint8_t checksum; + uint8_t padding; +}; + +struct bpreader_resp_02 { + struct bpreader_cmd_header; + uint8_t data; + struct bpreader_cmd_footer; +}; + +struct bpreader_resp_03 { + struct bpreader_cmd_header; + uint8_t data[2]; + struct bpreader_cmd_footer; +}; + +struct bpreader_resp_04 { + struct bpreader_cmd_header; + uint8_t data[3]; + struct bpreader_cmd_footer; +}; + +struct bpreader_resp_05 { + struct bpreader_cmd_header; + uint8_t data[4]; + struct bpreader_cmd_footer; +}; + +struct bpreader_resp_0A { + struct bpreader_cmd_header; + uint8_t data[9]; + struct bpreader_cmd_footer; +}; \ No newline at end of file