easyhack/easytool/easytool.c

184 lines
4.8 KiB
C

/* A reverse-engineered implementation of the EasyCard data format */
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
/* System includes */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <netinet/in.h>
/* libnfc includes */
#include <nfc/nfc-types.h>
#include <nfc/mifaretag.h>
#include "mifare_classic.h"
/* Easycard specific includes */
#include "easycard.h"
#define VERSION "0.01"
#define COPYRIGHT \
"EasyTool "VERSION"\n" \
"(C) 2010 by Harald Welte <laforge@gnumonks.org>\n" \
"This is FREE SOFTWARE with ABSOLUTELY NO VARRANTY\n\n" \
"Use of this software is only authorized for RESEARCH PURPOSE!\n\n"
struct {
int fd;
unsigned long size;
mifare_tag *mft;
} global;
static void dump_easy_log(const struct easy_log_rec *elr)
{
printf("%s | %02x | %10s | Paid %4u NTD | %4u NTD remaining\n",
easy_asc_timestamp(elr->timestamp),
elr->trans_id,
get_value_string(easy_tt_names, elr->trans_type),
elr->amount, elr->remaining);
switch (elr->trans_type) {
case EASY_TT_MRT_ENTER:
case EASY_TT_MRT_REENTER:
case EASY_TT_MRT_EXIT:
printf("\tMRT Station %s\n",
get_value_string(taipei_mrt_stn_id,
elr->station_code));
break;
}
}
static void dump_acc_bits(const struct acc_bits_parsed *abp)
{
uint8_t block;
for (block = 0; block < 4; block++) {
printf("\tBlock %u: %x (%u %u %u)\n", block, abp->block[block],
abp->block[block] & ABP_C1 ? 1 : 0,
abp->block[block] & ABP_C2 ? 1 : 0,
abp->block[block] & ABP_C3 ? 1 : 0);
}
}
static void dump_mfcl(mifare_tag *mft)
{
unsigned int sect;
mifare_block_manufacturer *manuf = &mft->amb[0].mbm;
printf("UID %x, ATQA %x\n", ntohl(*((uint32_t *) manuf->abtUID)),
ntohs(*((uint16_t *) manuf->abtATQA)));
for (sect = 0; sect < 16; sect++) {
unsigned int block_base = sect * 4;
uint8_t *access_bits = mft->amb[block_base+3].mbt.abtAccessBits;
struct acc_bits_parsed abp;
printf("Sector %02u (base: 0x%02x) Access bits: 0x%08x\n", sect,
sect*4*16, ntohl(*((uint32_t *) access_bits)));
mfcl_parse_acc_bits(&abp, access_bits);
dump_acc_bits(&abp);
}
}
static void dump_easycard(mifare_tag *mft)
{
unsigned int sect;
mifare_block_manufacturer *manuf = &mft->amb[0].mbm;
struct mfcl_value_block *val =
(struct mfcl_value_block *) mft->amb[8].mbd.abtData;
struct easy_block2sec0 *b2s0 =
(struct easy_block2sec0 *) mft->amb[1*4+0].mbd.abtData;
struct easy_block15sec2 *b15s2 =
(struct easy_block15sec2 *) mft->amb[15*4+2].mbd.abtData;
uint32_t uid = *((uint32_t *) manuf->abtUID);
/* dump the header */
printf("EasyCard UID 0x%08x (%u)\n", ntohl(uid), uid);
printf("Date of manufacture: %s\n",
easy_asc_timestamp(b2s0->timestamp));
printf("Current Balance: %5u NTD\n", val->value);
printf("Sum of all purchases on day %u (of month): %u NTD\n",
b15s2->day_of_month, b15s2->sum_of_day);
printf("\nTransaction Log:\n");
/* dump the transaction log */
for (sect = 3; sect < 6; sect++) {
unsigned int block_base = sect * 4;
unsigned int i;
for (i = 0; i < 3; i++) {
void *data = mft->amb[block_base+i].mbd.abtData;
/* first block of sector 3 is not a log record */
if (sect == 3 && i == 0)
continue;
dump_easy_log(data);
}
}
}
static void print_help(void)
{
}
int main(int argc, char **argv)
{
struct stat st;
printf(COPYRIGHT);
if (argc < 2) {
fprintf(stderr, "ERROR: You must specify the file name of "
"a mifare dump file (.mfd)\n");
print_help();
exit(2);
}
global.fd = open(argv[1], O_RDONLY);
if (global.fd < 0) {
perror("Error opening the MFD file");
exit(1);
}
if (fstat(global.fd, &st) < 0) {
perror("Error stat()ing the MFD file");
exit(1);
}
global.size = st.st_size;
global.mft = mmap(NULL, global.size, PROT_READ, MAP_SHARED,
global.fd, 0);
if (!global.mft) {
perror("Error mmap()ing the MFD file");
exit(1);
}
//dump_mfcl(global.mft);
dump_easycard(global.mft);
munmap(global.mft, global.size);
close(global.fd);
exit(0);
}