2010-02-21 08:47:22 +08:00
//-----------------------------------------------------------------------------
2010-02-26 05:57:35 +08:00
// Copyright (C) 2009 Michael Gernoth <michael at gernoth.net>
2010-02-21 08:47:22 +08:00
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// Main binary
//-----------------------------------------------------------------------------
2019-09-05 21:52:40 +08:00
# include "proxmark3.h"
2020-01-06 04:45:29 +08:00
2010-02-07 08:31:32 +08:00
# include <stdlib.h>
2020-01-06 04:45:29 +08:00
# include <stdio.h> // for Mingw readline
# include <limits.h>
2011-06-18 02:39:54 +08:00
# include <unistd.h>
2009-04-09 14:43:20 +08:00
# include <readline/readline.h>
# include <readline/history.h>
2019-08-08 22:57:33 +08:00
# include "usart_defs.h"
2018-09-07 03:43:20 +08:00
# include "util_posix.h"
2009-04-09 14:43:20 +08:00
# include "proxgui.h"
Client cleanup and restructuring. Stage 1...
Next Step is refactoring some of the giant functions which are
just copy/paste of some other ones with just a few line changes,
removing unnecessary 'goto' etc.
The MS Windows version is broken with this commit but will be fixed
soon. Everything can't be done all at once :P
The commands are now hierarchical, for example:
"hf 14a read" vs. "hf 14b read".
You can also request help:
"hf help", "data help", "hf 15 help" etc.
Indents are now space-based, not tab-based anymore. Hopefully
no one will be trolling about it, considering the suicide-prone work
being done here ;)
client/cmdhw.c, client/proxusb.c, client/cmdhw.h, client/proxusb.h,
client/cmdmain.c, client/cmdlfhid.c, client/cmdmain.h, client/cmdlfhid.h,
client/data.c, client/data.h, client/cmdhf.c, client/cmdlf.c,
client/cmdhf.h, client/cmdhf15.c, client/cmdhf14b.c, client/cmdlf.h,
client/cmdhf15.h, client/cmdhf14b.h, client/cmddata.c, client/cmddata.h,
client/ui.c, client/cmdparser.c, client/cmdlfti.c, client/ui.h,
client/cmdlfem4x.c, client/cmdparser.h, client/cmdlfti.h, client/cmdlfem4x.h,
client/graph.c, client/graph.h, client/cmdhf14a.c, client/cmdhf14a.h,
client/cmdhflegic.c, client/cmdhflegic.c: New files.
client/cli.c, client/flasher.c, client/snooper.c, client/proxmark3.c,
client/proxmark3.h, client/Makefile: Update accordingly.
client/flash.h, client/flash.c, client/proxgui.cpp: Cosmetic changes.
client/translate.h, client/command.c, client/gui.c,
client/usb.c, client/prox.h: Remove.
include/usb_cmd.h (CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM): Remove dead cmd.
common/crc16.h: New file.
common/crc16.c: Modify accordingly.
common/iso14443crc.h: New file.
common/iso14443_crc.c: Rename to
common/iso14443crc.c: and modify accordingly.
armsrc/lfops.c, armsrc/iso14443.c,
armsrc/iso14443a.c: include .h files from
the common directory instead of including the c files.
common/Makefile.common, armsrc/Makefile: Modify accordingly.
2010-02-04 09:27:07 +08:00
# include "cmdmain.h"
2012-12-05 07:39:18 +08:00
# include "ui.h"
2015-06-25 18:22:34 +08:00
# include "cmdhw.h"
2017-02-24 22:00:49 +08:00
# include "whereami.h"
2018-09-07 03:43:20 +08:00
# include "comms.h"
2019-09-05 05:29:03 +08:00
# include "fileutils.h"
2019-09-09 07:07:46 +08:00
# include "flash.h"
2020-04-12 11:07:25 +08:00
# include "preferences.h"
2020-04-14 17:17:00 +08:00
# ifdef _WIN32
# include <direct.h>
# define GetCurrentDir _getcwd
# else
# include <unistd.h>
# define GetCurrentDir getcwd
# endif
2020-04-12 11:07:25 +08:00
// Used to enable/disable use of preferences json file
2020-04-15 15:42:11 +08:00
// #define USE_PREFERENCE_FILE
2020-04-12 11:07:25 +08:00
# ifdef _WIN32
2020-04-16 15:01:14 +08:00
static void utf8_showBanner ( void ) {
char sq [ ] = { 0xE2 , 0x96 , 0x88 , 0x00 } ; // square block
char tr [ ] = { 0xE2 , 0x95 , 0x97 , 0x00 } ; // top rigth corner
char tl [ ] = { 0xE2 , 0x95 , 0x94 , 0x00 } ; // top left corner
char br [ ] = { 0xE2 , 0x95 , 0x9D , 0x00 } ; // bottom right corner
char bl [ ] = { 0xE2 , 0x95 , 0x9A , 0x00 } ; // bottom left corner
char hl [ ] = { 0xE2 , 0x95 , 0x90 , 0x00 } ; // horiz line
char vl [ ] = { 0xE2 , 0x95 , 0x91 , 0x00 } ; // vert line
2020-04-12 11:07:25 +08:00
char msg1 [ 60 ] ;
char msg2 [ 60 ] ;
char msg3 [ 60 ] ;
2020-04-16 15:01:14 +08:00
strcpy ( msg1 , " :snowflake: iceman@icesql.net :coffee: " ) ;
strcpy ( msg2 , " https://github.com/rfidresearchgroup/proxmark3/ " ) ;
strcpy ( msg3 , " pre-release v4.0 " ) ;
2019-09-05 21:52:40 +08:00
2020-04-12 11:07:25 +08:00
g_printAndLog = PRINTANDLOG_PRINT ;
PrintAndLogEx ( NORMAL , " \n " ) ;
2020-04-10 17:51:08 +08:00
2020-04-16 15:01:14 +08:00
PrintAndLogEx ( NORMAL , " " _BLUE_ ( " %s%s%s%s%s%s%s %s%s%s%s %s%s%s%s %s%s%s%s%s " ) , sq , sq , sq , sq , sq , sq , tr , sq , sq , sq , tr , sq , sq , sq , tr , sq , sq , sq , sq , tr ) ;
PrintAndLogEx ( NORMAL , " " _BLUE_ ( " %s%s%s%s%s%s%s%s%s%s%s%s%s %s%s%s%s%s %s%s%s%s " ) , sq , sq , tl , hl , hl , sq , sq , tr , sq , sq , sq , sq , tr , sq , sq , sq , sq , vl , hl , hl , sq , vl ) ;
PrintAndLogEx ( NORMAL , " " _BLUE_ ( " %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s %s%s%s%s%s%s " ) , sq , sq , sq , sq , sq , sq , tl , br , sq , sq , tl , sq , sq , sq , sq , tl , sq , sq , vl , sq , sq , sq , sq , tl , br ) ;
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( NORMAL , " " _BLUE_ ( " %s%s%s%s%s%s%s %s%s%s%s%s%s%s%s%s%s%s %s%s%s%s " ) " %s " , sq , sq , tr , hl , hl , hl , br , sq , sq , vl , bl , sq , sq , tl , br , sq , sq , vl , hl , hl , sq , vl , msg1 ) ;
PrintAndLogEx ( NORMAL , " " _BLUE_ ( " %s%s%s %s%s%s %s%s%s %s%s%s %s%s%s%s%s%s " ) " %s " , sq , sq , vl , sq , sq , vl , bl , hl , br , sq , sq , vl , sq , sq , sq , sq , tl , br , msg2 ) ;
PrintAndLogEx ( NORMAL , " " _BLUE_ ( " %s%s%s %s%s%s %s%s%s %s%s%s%s%s " ) " %s " , bl , hl , br , bl , hl , br , bl , hl , br , bl , hl , hl , hl , br , msg3 ) ;
2020-04-12 11:07:25 +08:00
PrintAndLogEx ( NORMAL , " " ) ;
fflush ( stdout ) ;
g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG ;
}
# endif
2020-04-10 17:51:08 +08:00
2019-03-10 18:20:22 +08:00
static void showBanner ( void ) {
2020-04-12 11:07:25 +08:00
# ifdef _WIN32
// If on windows and using UTF-8 then we need utf-8 ascii art for banner.
if ( GetConsoleCP ( ) = = 65001 ) {
2020-04-16 15:01:14 +08:00
utf8_showBanner ( ) ;
2020-04-12 11:07:25 +08:00
return ;
}
# endif
2019-10-16 20:46:57 +08:00
g_printAndLog = PRINTANDLOG_PRINT ;
2019-04-30 06:41:52 +08:00
PrintAndLogEx ( NORMAL , " \n " ) ;
2019-08-28 06:03:27 +08:00
# if defined(__linux__) || (__APPLE__) || (_WIN32)
2019-12-11 22:56:36 +08:00
PrintAndLogEx ( NORMAL , " " _BLUE_ ( " ██████╗ ███╗ ███╗ ████╗ " ) ) ;
2019-12-06 15:51:24 +08:00
PrintAndLogEx ( NORMAL , " " _BLUE_ ( " ██╔══██╗████╗ ████║ ══█║ " ) ) ;
PrintAndLogEx ( NORMAL , " " _BLUE_ ( " ██████╔╝██╔████╔██║ ████╔╝ " ) ) ;
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( NORMAL , " " _BLUE_ ( " ██╔═══╝ ██║╚██╔╝██║ ══█║ " ) " :snowflake: iceman@icesql.net :coffee: " ) ;
PrintAndLogEx ( NORMAL , " " _BLUE_ ( " ██║ ██║ ╚═╝ ██║ ████╔╝ " ) " https://github.com/rfidresearchgroup/proxmark3/ " ) ;
PrintAndLogEx ( NORMAL , " " _BLUE_ ( " ╚═╝ ╚═╝ ╚═╝ ╚═══╝ " ) " pre-release v4.0 " ) ;
2019-04-13 19:34:02 +08:00
# else
2019-12-11 22:56:36 +08:00
PrintAndLogEx ( NORMAL , " ======. ===. ===. ====. " ) ;
2019-12-06 15:51:24 +08:00
PrintAndLogEx ( NORMAL , " ==...==.====. ====. ..=. " ) ;
PrintAndLogEx ( NORMAL , " ======..==.====.==. ====.. " ) ;
2020-03-17 04:45:17 +08:00
PrintAndLogEx ( NORMAL , " ==..... ==..==..==. ..=. iceman@icesql.net :coffee: " ) ;
2019-12-06 15:51:24 +08:00
PrintAndLogEx ( NORMAL , " ==. ==. ... ==. ====.. https://github.com/rfidresearchgroup/proxmark3/ " ) ;
PrintAndLogEx ( NORMAL , " ... ... ... ..... pre-release v4.0 " ) ;
2019-04-13 19:34:02 +08:00
# endif
2019-12-06 15:51:24 +08:00
// PrintAndLogEx(NORMAL, "\nSupport iceman on patreon - https://www.patreon.com/iceman1001/");
// PrintAndLogEx(NORMAL, " on paypal - https://www.paypal.me/iceman1001");
2019-04-13 19:34:02 +08:00
// printf("\nMonero: 43mNJLpgBVaTvyZmX9ajcohpvVkaRy1kbZPm8tqAb7itZgfuYecgkRF36rXrKFUkwEGeZedPsASRxgv4HPBHvJwyJdyvQuP");
2019-12-06 15:51:24 +08:00
PrintAndLogEx ( NORMAL , " " ) ;
2019-03-10 06:35:06 +08:00
fflush ( stdout ) ;
2019-10-16 20:46:57 +08:00
g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG ;
2017-07-31 21:12:38 +08:00
}
2016-09-09 17:56:20 +08:00
2020-04-12 11:07:25 +08:00
2019-10-25 06:55:16 +08:00
static int check_comm ( void ) {
2019-05-07 07:06:01 +08:00
// If communications thread goes down. Device disconnected then this should hook up PM3 again.
2019-05-08 07:35:51 +08:00
if ( IsCommunicationThreadDead ( ) & & session . pm3_present ) {
2020-04-22 08:22:55 +08:00
rl_set_prompt ( PROXPROMPT_OFFLINE ) ;
2020-03-19 12:44:47 +08:00
2019-05-08 07:35:51 +08:00
rl_forced_update_display ( ) ;
CloseProxmark ( ) ;
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( INFO , " Running in " _YELLOW_ ( " OFFLINE " ) " mode. Use " _YELLOW_ ( " \" hw connect \" " ) " to reconnect \n " ) ;
2019-05-07 07:06:01 +08:00
}
return 0 ;
}
2019-09-10 05:46:38 +08:00
// first slot is always NULL, indicating absence of script when idx=0
FILE * cmdscriptfile [ MAX_NESTED_CMDSCRIPT + 1 ] = { 0 } ;
uint8_t cmdscriptfile_idx = 0 ;
bool cmdscriptfile_stayafter = false ;
int push_cmdscriptfile ( char * path , bool stayafter ) {
if ( cmdscriptfile_idx = = MAX_NESTED_CMDSCRIPT ) {
PrintAndLogEx ( ERR , " Too many nested scripts, skipping %s \n " , path ) ;
return PM3_EMALLOC ;
}
FILE * tmp = fopen ( path , " r " ) ;
if ( tmp = = NULL )
return PM3_EFILE ;
if ( cmdscriptfile_idx = = 0 )
cmdscriptfile_stayafter = stayafter ;
cmdscriptfile [ + + cmdscriptfile_idx ] = tmp ;
return PM3_SUCCESS ;
}
2019-10-25 06:55:16 +08:00
static FILE * current_cmdscriptfile ( ) {
2019-09-10 05:46:38 +08:00
return cmdscriptfile [ cmdscriptfile_idx ] ;
}
2019-10-27 00:49:25 +08:00
static bool pop_cmdscriptfile ( ) {
2019-09-10 05:46:38 +08:00
fclose ( cmdscriptfile [ cmdscriptfile_idx ] ) ;
cmdscriptfile [ cmdscriptfile_idx - - ] = NULL ;
if ( cmdscriptfile_idx = = 0 )
return cmdscriptfile_stayafter ;
else
return true ;
}
2019-05-06 20:11:23 +08:00
// Main thread of PM3 Client
2018-02-01 22:24:36 +08:00
void
# ifdef __has_attribute
# if __has_attribute(force_align_arg_pointer)
2019-03-09 15:59:13 +08:00
__attribute__ ( ( force_align_arg_pointer ) )
2018-02-01 22:24:36 +08:00
# endif
# endif
2019-08-04 21:34:18 +08:00
main_loop ( char * script_cmds_file , char * script_cmd , bool stayInCommandLoop ) {
2017-09-26 23:04:25 +08:00
2019-03-10 06:35:06 +08:00
char * cmd = NULL ;
bool execCommand = ( script_cmd ! = NULL ) ;
2019-04-27 22:52:23 +08:00
uint16_t script_cmd_len = 0 ;
if ( execCommand ) {
script_cmd_len = strlen ( script_cmd ) ;
2019-04-27 06:30:44 +08:00
strcreplace ( script_cmd , script_cmd_len , ' ; ' , ' \0 ' ) ;
2019-04-27 22:52:23 +08:00
}
2019-03-10 06:35:06 +08:00
bool stdinOnPipe = ! isatty ( STDIN_FILENO ) ;
char script_cmd_buf [ 256 ] = { 0x00 } ; // iceman, needs lua script the same file_path_buffer as the rest
PrintAndLogEx ( DEBUG , " ISATTY/STDIN_FILENO == %s \n " , ( stdinOnPipe ) ? " true " : " false " ) ;
2019-05-01 05:52:40 +08:00
if ( session . pm3_present ) {
2019-03-10 06:35:06 +08:00
// cache Version information now:
2019-03-10 07:00:59 +08:00
if ( execCommand | | script_cmds_file | | stdinOnPipe )
2019-08-21 18:52:59 +08:00
pm3_version ( false , false ) ;
2019-03-10 06:35:06 +08:00
else
2019-08-21 18:52:59 +08:00
pm3_version ( true , false ) ;
2019-03-10 06:35:06 +08:00
}
if ( script_cmds_file ) {
2019-09-05 05:29:03 +08:00
char * path ;
int res = searchFile ( & path , CMD_SCRIPTS_SUBDIR , script_cmds_file , " .cmd " , false ) ;
if ( res = = PM3_SUCCESS ) {
2019-09-10 05:46:38 +08:00
if ( push_cmdscriptfile ( path , stayInCommandLoop ) = = PM3_SUCCESS )
2019-09-05 05:29:03 +08:00
PrintAndLogEx ( SUCCESS , " executing commands from file: %s \n " , path ) ;
else
PrintAndLogEx ( ERR , " could not open " _YELLOW_ ( " %s " ) " ... " , path ) ;
free ( path ) ;
}
2019-03-10 06:35:06 +08:00
}
2019-08-29 03:15:11 +08:00
char * my_history_path = NULL ;
if ( searchHomeFilePath ( & my_history_path , PROXHISTORY , true ) ! = PM3_SUCCESS ) {
2019-08-29 16:31:37 +08:00
PrintAndLogEx ( ERR , " No history will be recorded " ) ;
2019-08-29 03:15:11 +08:00
my_history_path = NULL ;
} else {
read_history ( my_history_path ) ;
}
2019-03-10 06:35:06 +08:00
// loops every time enter is pressed...
while ( 1 ) {
2019-04-29 04:38:44 +08:00
bool printprompt = false ;
2020-04-22 08:22:55 +08:00
const char * prompt = PROXPROMPT_CON ;
2019-03-10 06:35:06 +08:00
2019-09-10 05:46:38 +08:00
check_script :
2019-03-10 06:35:06 +08:00
// If there is a script file
2019-09-10 05:46:38 +08:00
if ( current_cmdscriptfile ( ) ) {
2019-03-10 06:35:06 +08:00
// clear array
memset ( script_cmd_buf , 0 , sizeof ( script_cmd_buf ) ) ;
// read script file
2019-10-09 19:44:51 +08:00
if ( fgets ( script_cmd_buf , sizeof ( script_cmd_buf ) , current_cmdscriptfile ( ) ) = = NULL ) {
2019-09-10 05:46:38 +08:00
if ( ! pop_cmdscriptfile ( ) )
break ;
goto check_script ;
2019-03-10 06:35:06 +08:00
} else {
// remove linebreaks
strcleanrn ( script_cmd_buf , sizeof ( script_cmd_buf ) ) ;
2020-01-06 05:24:24 +08:00
cmd = str_dup ( script_cmd_buf ) ;
2020-01-06 04:45:29 +08:00
if ( cmd ! = NULL )
2019-04-29 04:38:44 +08:00
printprompt = true ;
2019-03-10 06:35:06 +08:00
}
} else {
// If there is a script command
2019-03-10 07:00:59 +08:00
if ( execCommand ) {
2020-01-06 04:45:29 +08:00
2020-01-06 05:24:24 +08:00
cmd = str_dup ( script_cmd ) ;
2020-01-06 04:45:29 +08:00
if ( cmd ! = NULL )
2019-04-29 04:38:44 +08:00
printprompt = true ;
2020-01-04 23:25:31 +08:00
2019-04-27 06:30:44 +08:00
uint16_t len = strlen ( script_cmd ) + 1 ;
script_cmd + = len ;
2020-01-04 23:25:31 +08:00
2019-04-27 06:30:44 +08:00
if ( script_cmd_len = = len - 1 )
execCommand = false ;
2020-01-04 23:25:31 +08:00
2019-04-27 06:30:44 +08:00
script_cmd_len - = len ;
2019-03-10 06:35:06 +08:00
} else {
// exit after exec command
2019-08-04 21:34:18 +08:00
if ( script_cmd & & ! stayInCommandLoop )
2019-03-10 06:35:06 +08:00
break ;
// if there is a pipe from stdin
if ( stdinOnPipe ) {
// clear array
memset ( script_cmd_buf , 0 , sizeof ( script_cmd_buf ) ) ;
// get
2019-05-01 04:03:20 +08:00
if ( fgets ( script_cmd_buf , sizeof ( script_cmd_buf ) , stdin ) = = NULL ) {
2019-03-10 06:35:06 +08:00
PrintAndLogEx ( ERR , " STDIN unexpected end, exit... " ) ;
break ;
}
// remove linebreaks
strcleanrn ( script_cmd_buf , sizeof ( script_cmd_buf ) ) ;
2020-01-06 05:24:24 +08:00
cmd = str_dup ( script_cmd_buf ) ;
2020-01-06 04:45:29 +08:00
if ( cmd ! = NULL )
2019-04-29 04:38:44 +08:00
printprompt = true ;
2019-03-10 06:35:06 +08:00
} else {
2019-05-07 18:11:36 +08:00
rl_event_hook = check_comm ;
2019-05-19 00:02:30 +08:00
if ( session . pm3_present ) {
2019-06-08 03:40:33 +08:00
if ( conn . send_via_fpc_usart = = false )
2020-04-22 08:22:55 +08:00
prompt = PROXPROMPT_USB ;
2019-06-08 03:40:33 +08:00
else
2020-04-22 08:22:55 +08:00
prompt = PROXPROMPT_FPC ;
2020-01-04 23:25:31 +08:00
} else {
2020-04-22 08:22:55 +08:00
prompt = PROXPROMPT_OFFLINE ;
2020-01-04 23:25:31 +08:00
}
2020-04-22 15:32:32 +08:00
char prompt_filtered [ PROXPROMPT_MAX_SIZE ] = { 0 } ;
memcpy_filter_ansi ( prompt_filtered , prompt , sizeof ( prompt_filtered ) , ! session . supports_colors ) ;
cmd = readline ( prompt_filtered ) ;
2019-03-10 06:35:06 +08:00
fflush ( NULL ) ;
}
}
}
// execute command
if ( cmd ) {
// rtrim
size_t l = strlen ( cmd ) ;
2019-04-29 04:38:44 +08:00
while ( l > 0 & & isspace ( cmd [ l - 1 ] ) ) {
cmd [ - - l ] = ' \0 ' ;
}
// ltrim
2019-04-29 04:54:00 +08:00
size_t off = 0 ;
2020-01-04 23:25:31 +08:00
while ( ( cmd [ off ] ! = ' \0 ' ) & & isspace ( cmd [ off ] ) ) {
2019-04-29 04:38:44 +08:00
off + + ;
2020-01-04 23:25:31 +08:00
}
for ( size_t i = 0 ; i < strlen ( cmd ) - off ; i + + ) {
2019-04-29 04:54:00 +08:00
cmd [ i ] = cmd [ i + off ] ;
2020-01-04 23:25:31 +08:00
}
2019-04-29 04:38:44 +08:00
cmd [ strlen ( cmd ) - off ] = ' \0 ' ;
if ( cmd [ 0 ] ! = ' \0 ' ) {
2020-01-04 23:25:31 +08:00
if ( ! printprompt ) {
2019-09-10 03:30:25 +08:00
g_printAndLog = PRINTANDLOG_LOG ;
2020-01-04 23:25:31 +08:00
}
2019-09-10 03:30:25 +08:00
PrintAndLogEx ( NORMAL , " %s%s " , prompt , cmd ) ;
g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG ;
2019-05-08 07:35:51 +08:00
2019-09-10 05:46:38 +08:00
// add to history if not from a script
if ( ! current_cmdscriptfile ( ) ) {
HIST_ENTRY * entry = history_get ( history_length ) ;
// add if not identical to latest recorded cmd
2020-01-04 23:25:31 +08:00
if ( ( ! entry ) | | ( strcmp ( entry - > line , cmd ) ! = 0 ) ) {
2019-09-10 05:46:38 +08:00
add_history ( cmd ) ;
2020-01-04 23:25:31 +08:00
}
2019-09-10 05:46:38 +08:00
}
// process cmd
2019-03-10 06:35:06 +08:00
int ret = CommandReceived ( cmd ) ;
// exit or quit
2019-04-19 06:42:25 +08:00
if ( ret = = PM3_EFATAL )
2019-03-10 06:35:06 +08:00
break ;
}
free ( cmd ) ;
cmd = NULL ;
} else {
PrintAndLogEx ( NORMAL , " \n " ) ;
2019-08-04 21:34:18 +08:00
if ( script_cmds_file & & stayInCommandLoop )
stayInCommandLoop = false ;
else
break ;
2019-03-10 06:35:06 +08:00
}
} // end while
2019-10-04 15:30:36 +08:00
if ( session . pm3_present ) {
clearCommandBuffer ( ) ;
SendCommandNG ( CMD_QUIT_SESSION , NULL , 0 ) ;
msleep ( 100 ) ; // Make sure command is sent before killing client
}
2019-06-03 05:20:02 +08:00
2019-09-10 05:46:38 +08:00
while ( current_cmdscriptfile ( ) )
pop_cmdscriptfile ( ) ;
2019-03-10 06:35:06 +08:00
2019-08-29 03:15:11 +08:00
if ( my_history_path ) {
write_history ( my_history_path ) ;
free ( my_history_path ) ;
}
2020-01-04 23:25:31 +08:00
2019-03-10 06:35:06 +08:00
if ( cmd ) {
free ( cmd ) ;
cmd = NULL ;
}
2009-04-09 14:43:20 +08:00
}
2019-03-10 18:20:22 +08:00
static void dumpAllHelp ( int markdown ) {
2019-05-02 02:48:15 +08:00
session . help_dump_mode = true ;
2019-03-10 06:35:06 +08:00
PrintAndLogEx ( NORMAL , " \n %sProxmark3 command dump%s \n \n " , markdown ? " # " : " " , markdown ? " " : " \n ====================== " ) ;
2019-04-17 02:00:25 +08:00
PrintAndLogEx ( NORMAL , " Some commands are available only if a Proxmark3 is actually connected.%s \n " , markdown ? " " : " " ) ;
2019-03-10 06:35:06 +08:00
PrintAndLogEx ( NORMAL , " Check column \" offline \" for their availability. \n " ) ;
PrintAndLogEx ( NORMAL , " \n " ) ;
command_t * cmds = getTopLevelCommandTable ( ) ;
dumpCommandsRecursive ( cmds , markdown ) ;
2019-05-02 02:48:15 +08:00
session . help_dump_mode = false ;
2014-03-27 05:08:55 +08:00
}
2017-02-24 22:00:49 +08:00
static char * my_executable_path = NULL ;
static char * my_executable_directory = NULL ;
2019-03-10 18:20:22 +08:00
const char * get_my_executable_path ( void ) {
2019-03-10 06:35:06 +08:00
return my_executable_path ;
2017-02-24 22:00:49 +08:00
}
2019-03-10 18:20:22 +08:00
const char * get_my_executable_directory ( void ) {
2019-03-10 06:35:06 +08:00
return my_executable_directory ;
2017-02-24 22:00:49 +08:00
}
2019-03-10 18:20:22 +08:00
static void set_my_executable_path ( void ) {
2019-03-10 06:35:06 +08:00
int path_length = wai_getExecutablePath ( NULL , 0 , NULL ) ;
2019-04-14 17:43:05 +08:00
if ( path_length = = - 1 )
2019-04-13 19:34:02 +08:00
return ;
2019-04-14 17:43:05 +08:00
2019-04-13 19:34:02 +08:00
my_executable_path = ( char * ) calloc ( path_length + 1 , sizeof ( uint8_t ) ) ;
int dirname_length = 0 ;
if ( wai_getExecutablePath ( my_executable_path , path_length , & dirname_length ) ! = - 1 ) {
my_executable_path [ path_length ] = ' \0 ' ;
my_executable_directory = ( char * ) calloc ( dirname_length + 2 , sizeof ( uint8_t ) ) ;
strncpy ( my_executable_directory , my_executable_path , dirname_length + 1 ) ;
my_executable_directory [ dirname_length + 1 ] = ' \0 ' ;
2019-03-10 06:35:06 +08:00
}
2017-02-24 22:00:49 +08:00
}
2019-10-27 01:40:32 +08:00
static const char * my_user_directory = NULL ;
2020-04-14 17:17:00 +08:00
static char _cwd_Buffer [ FILENAME_MAX ] = { 0 } ;
2019-09-13 02:13:01 +08:00
const char * get_my_user_directory ( void ) {
return my_user_directory ;
}
static void set_my_user_directory ( void ) {
my_user_directory = getenv ( " HOME " ) ;
2020-04-15 14:40:28 +08:00
2019-09-13 02:16:52 +08:00
// if not found, default to current directory
2020-04-14 17:17:00 +08:00
if ( my_user_directory = = NULL ) {
2020-04-16 15:01:14 +08:00
my_user_directory = GetCurrentDir ( _cwd_Buffer , sizeof ( _cwd_Buffer ) ) ;
2020-04-14 17:17:00 +08:00
// change all slashs to / (windows should not care...
for ( int i = 0 ; i < strlen ( _cwd_Buffer ) ; i + + )
if ( _cwd_Buffer [ i ] = = ' \\ ' ) _cwd_Buffer [ i ] = ' / ' ;
2020-04-16 15:01:14 +08:00
// my_user_directory = ".";
2020-04-14 17:17:00 +08:00
}
2019-09-13 02:13:01 +08:00
}
2019-04-14 19:35:52 +08:00
static void show_help ( bool showFullHelp , char * exec_name ) {
2019-04-14 18:54:13 +08:00
2019-09-09 07:07:46 +08:00
PrintAndLogEx ( NORMAL , " \n syntax: %s [-h|-t|-m] " , exec_name ) ;
2019-09-10 02:45:10 +08:00
PrintAndLogEx ( NORMAL , " %s [[-p] <port>] [-b] [-w] [-f] [-c <command>]|[-l <lua_script_file>]|[-s <cmd_script_file>] [-i] [-d <0|1|2>] " , exec_name ) ;
PrintAndLogEx ( NORMAL , " %s [-p] <port> --flash [--unlock-bootloader] [--image <imagefile>]+ [-w] [-f] [-d <0|1|2>] " , exec_name ) ;
2019-03-10 06:35:06 +08:00
2019-03-10 07:00:59 +08:00
if ( showFullHelp ) {
2019-09-10 02:45:10 +08:00
PrintAndLogEx ( NORMAL , " \n Common options: " ) ;
2019-04-14 18:54:13 +08:00
PrintAndLogEx ( NORMAL , " -h/--help this help " ) ;
2019-09-10 02:45:10 +08:00
PrintAndLogEx ( NORMAL , " -v/--version print client version " ) ;
2019-04-14 18:54:13 +08:00
PrintAndLogEx ( NORMAL , " -p/--port serial port to connect to " ) ;
PrintAndLogEx ( NORMAL , " -w/--wait 20sec waiting the serial port to appear in the OS " ) ;
PrintAndLogEx ( NORMAL , " -f/--flush output will be flushed after every print " ) ;
2019-09-10 02:45:10 +08:00
PrintAndLogEx ( NORMAL , " -d/--debug <0|1|2> set debugmode " ) ;
PrintAndLogEx ( NORMAL , " \n Options in client mode: " ) ;
PrintAndLogEx ( NORMAL , " -t/--text dump all interactive command's help at once " ) ;
PrintAndLogEx ( NORMAL , " -m/--markdown dump all interactive help at once in markdown syntax " ) ;
PrintAndLogEx ( NORMAL , " -b/--baud serial port speed (only needed for physical UART, not for USB-CDC or BT) " ) ;
2019-05-19 00:02:30 +08:00
PrintAndLogEx ( NORMAL , " -c/--command <command> execute one Proxmark3 command (or several separated by ';'). " ) ;
2019-04-14 18:54:13 +08:00
PrintAndLogEx ( NORMAL , " -l/--lua <lua script file> execute lua script. " ) ;
2019-05-19 00:02:30 +08:00
PrintAndLogEx ( NORMAL , " -s/--script-file <cmd_script_file> script file with one Proxmark3 command per line " ) ;
2019-08-04 21:34:18 +08:00
PrintAndLogEx ( NORMAL , " -i/--interactive enter interactive mode after executing the script or the command " ) ;
2019-09-09 07:07:46 +08:00
PrintAndLogEx ( NORMAL , " \n Options in flasher mode: " ) ;
PrintAndLogEx ( NORMAL , " --flash flash Proxmark3, requires at least one --image " ) ;
PrintAndLogEx ( NORMAL , " --unlock-bootloader Enable flashing of bootloader area *DANGEROUS* (need --flash or --flash-info) " ) ;
PrintAndLogEx ( NORMAL , " --image <imagefile> image to flash. Can be specified several times. " ) ;
PrintAndLogEx ( NORMAL , " \n Examples: " ) ;
PrintAndLogEx ( NORMAL , " \n to run Proxmark3 client: \n " ) ;
PrintAndLogEx ( NORMAL , " %s " SERIAL_PORT_EXAMPLE_H " -- runs the pm3 client " , exec_name ) ;
PrintAndLogEx ( NORMAL , " %s " SERIAL_PORT_EXAMPLE_H " -f -- flush output everytime " , exec_name ) ;
PrintAndLogEx ( NORMAL , " %s " SERIAL_PORT_EXAMPLE_H " -w -- wait for serial port " , exec_name ) ;
PrintAndLogEx ( NORMAL , " %s -- runs the pm3 client in OFFLINE mode " , exec_name ) ;
PrintAndLogEx ( NORMAL , " \n to execute different commands from terminal: \n " ) ;
PrintAndLogEx ( NORMAL , " %s " SERIAL_PORT_EXAMPLE_H " -c \" hf mf chk 1* ? \" -- execute cmd and quit client " , exec_name ) ;
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( NORMAL , " %s " SERIAL_PORT_EXAMPLE_H " -l hf_read -- execute lua script " _YELLOW_ ( " `hf_read` " ) " and quit client " , exec_name ) ;
2019-09-09 07:07:46 +08:00
PrintAndLogEx ( NORMAL , " %s " SERIAL_PORT_EXAMPLE_H " -s mycmds.txt -- execute each pm3 cmd in file and quit client " , exec_name ) ;
PrintAndLogEx ( NORMAL , " \n to flash fullimage and bootloader: \n " ) ;
PrintAndLogEx ( NORMAL , " %s " SERIAL_PORT_EXAMPLE_H " --flash --unlock-bootloader --image bootrom.elf --image fullimage.elf " , exec_name ) ;
# ifdef __linux__
2019-09-13 22:32:37 +08:00
PrintAndLogEx ( NORMAL , " \n Note (Linux): \n if the flasher gets stuck in 'Waiting for Proxmark3 to reappear on <DEVICE>', " ) ;
PrintAndLogEx ( NORMAL , " you need to blacklist Proxmark3 for modem-manager - see documentation for more details: " ) ;
PrintAndLogEx ( NORMAL , " * https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md " ) ;
PrintAndLogEx ( NORMAL , " \n More info on flashing procedure from the official Proxmark3 wiki: " ) ;
PrintAndLogEx ( NORMAL , " * https://github.com/Proxmark/proxmark3/wiki/Gentoo%%20Linux " ) ;
PrintAndLogEx ( NORMAL , " * https://github.com/Proxmark/proxmark3/wiki/Ubuntu%%20Linux " ) ;
PrintAndLogEx ( NORMAL , " * https://github.com/Proxmark/proxmark3/wiki/OSX \n " ) ;
2019-09-09 07:07:46 +08:00
# endif
}
}
static int flash_pm3 ( char * serial_port_name , uint8_t num_files , char * filenames [ FLASH_MAX_FILES ] , bool can_write_bl ) {
int ret = PM3_EUNDEF ;
flash_file_t files [ FLASH_MAX_FILES ] ;
memset ( files , 0 , sizeof ( files ) ) ;
2019-10-06 07:18:04 +08:00
char * filepaths [ FLASH_MAX_FILES ] = { 0 } ;
2019-09-09 07:07:46 +08:00
if ( serial_port_name = = NULL ) {
PrintAndLogEx ( ERR , " You must specify a port. \n " ) ;
return PM3_EINVARG ;
}
2019-09-10 01:55:27 +08:00
for ( int i = 0 ; i < num_files ; + + i ) {
char * path ;
ret = searchFile ( & path , FIRMWARES_SUBDIR , filenames [ i ] , " .elf " , true ) ;
if ( ret ! = PM3_SUCCESS ) {
ret = searchFile ( & path , BOOTROM_SUBDIR , filenames [ i ] , " .elf " , true ) ;
}
if ( ret ! = PM3_SUCCESS ) {
// Last try, let the error msg be displayed if not found
ret = searchFile ( & path , FULLIMAGE_SUBDIR , filenames [ i ] , " .elf " , false ) ;
}
if ( ret ! = PM3_SUCCESS ) {
goto finish2 ;
}
filepaths [ i ] = path ;
}
PrintAndLogEx ( SUCCESS , " About to use the following file%s: " , num_files > 1 ? " s " : " " ) ;
for ( int i = 0 ; i < num_files ; + + i ) {
PrintAndLogEx ( SUCCESS , " %s " , filepaths [ i ] ) ;
}
2019-09-09 07:07:46 +08:00
if ( OpenProxmark ( serial_port_name , true , 60 , true , FLASHMODE_SPEED ) ) {
PrintAndLogEx ( NORMAL , _GREEN_ ( " Found " ) ) ;
} else {
PrintAndLogEx ( ERR , " Could not find Proxmark3 on " _RED_ ( " %s " ) " . \n " , serial_port_name ) ;
2019-09-10 01:55:27 +08:00
ret = PM3_ETIMEOUT ;
goto finish2 ;
2019-09-09 07:07:46 +08:00
}
uint32_t max_allowed = 0 ;
ret = flash_start_flashing ( can_write_bl , serial_port_name , & max_allowed ) ;
if ( ret ! = PM3_SUCCESS ) {
goto finish ;
}
if ( num_files = = 0 )
goto finish ;
for ( int i = 0 ; i < num_files ; + + i ) {
2019-09-10 01:55:27 +08:00
ret = flash_load ( & files [ i ] , filepaths [ i ] , can_write_bl , max_allowed * ONE_KB ) ;
2019-09-09 07:07:46 +08:00
if ( ret ! = PM3_SUCCESS ) {
goto finish ;
}
PrintAndLogEx ( NORMAL , " " ) ;
2019-03-10 06:35:06 +08:00
}
2019-09-09 07:07:46 +08:00
PrintAndLogEx ( SUCCESS , " \n " _BLUE_ ( " Flashing... " ) ) ;
for ( int i = 0 ; i < num_files ; i + + ) {
ret = flash_write ( & files [ i ] ) ;
if ( ret ! = PM3_SUCCESS ) {
goto finish ;
}
flash_free ( & files [ i ] ) ;
PrintAndLogEx ( NORMAL , " \n " ) ;
}
finish :
ret = flash_stop_flashing ( ) ;
CloseProxmark ( ) ;
2019-09-10 01:55:27 +08:00
finish2 :
for ( int i = 0 ; i < num_files ; + + i ) {
if ( filepaths [ i ] ! = NULL )
free ( filepaths [ i ] ) ;
}
2019-09-09 07:07:46 +08:00
if ( ret = = PM3_SUCCESS )
PrintAndLogEx ( SUCCESS , _BLUE_ ( " All done. " ) ) ;
else
PrintAndLogEx ( ERR , " Aborted on error. " ) ;
PrintAndLogEx ( NORMAL , " \n Have a nice day! " ) ;
return ret ;
2017-10-21 02:39:57 +08:00
}
2020-04-12 11:07:25 +08:00
# ifndef USE_PREFERENCE_FILE
2020-04-10 17:51:08 +08:00
2019-10-16 20:46:57 +08:00
// Check if windows AnsiColor Support is enabled in the registery
// [HKEY_CURRENT_USER\Console]
// "VirtualTerminalLevel"=dword:00000001
2019-10-26 10:17:33 +08:00
// 2nd Key needs to be enabled... This key takes the console out of legacy mode.
// [HKEY_CURRENT_USER\Console]
// "ForceV2"=dword:00000001
2020-04-10 17:51:08 +08:00
2019-10-16 20:46:57 +08:00
static bool DetectWindowsAnsiSupport ( void ) {
bool ret = false ;
# if defined(_WIN32)
HKEY hKey = NULL ;
2019-10-26 10:17:33 +08:00
bool virtualTerminalLevelSet = false ;
bool forceV2Set = false ;
2019-10-29 20:35:09 +08:00
2019-10-16 20:46:57 +08:00
if ( RegOpenKeyA ( HKEY_CURRENT_USER , " Console " , & hKey ) = = ERROR_SUCCESS ) {
DWORD dwType = REG_SZ ;
BYTE KeyValue [ sizeof ( dwType ) ] ;
DWORD len = sizeof ( KeyValue ) ;
if ( RegQueryValueEx ( hKey , " VirtualTerminalLevel " , NULL , & dwType , KeyValue , & len ) ! = ERROR_FILE_NOT_FOUND ) {
uint8_t i ;
uint32_t Data = 0 ;
for ( i = 0 ; i < 4 ; i + + )
Data + = KeyValue [ i ] < < ( 8 * i ) ;
if ( Data = = 1 ) { // Reg key is set to 1, Ansi Color Enabled
2019-10-26 10:17:33 +08:00
virtualTerminalLevelSet = true ;
}
}
RegCloseKey ( hKey ) ;
}
if ( RegOpenKeyA ( HKEY_CURRENT_USER , " Console " , & hKey ) = = ERROR_SUCCESS ) {
DWORD dwType = REG_SZ ;
BYTE KeyValue [ sizeof ( dwType ) ] ;
DWORD len = sizeof ( KeyValue ) ;
if ( RegQueryValueEx ( hKey , " ForceV2 " , NULL , & dwType , KeyValue , & len ) ! = ERROR_FILE_NOT_FOUND ) {
uint8_t i ;
uint32_t Data = 0 ;
for ( i = 0 ; i < 4 ; i + + )
Data + = KeyValue [ i ] < < ( 8 * i ) ;
if ( Data = = 1 ) { // Reg key is set to 1, Not using legacy Mode.
forceV2Set = true ;
2019-10-16 20:46:57 +08:00
}
}
RegCloseKey ( hKey ) ;
}
2019-10-26 10:17:33 +08:00
// If both VirtualTerminalLevel and ForceV2 is set, AnsiColor should work
ret = virtualTerminalLevelSet & & forceV2Set ;
2019-10-16 20:46:57 +08:00
# endif
return ret ;
}
2020-04-10 17:51:08 +08:00
# endif
2019-03-10 18:20:22 +08:00
int main ( int argc , char * argv [ ] ) {
2019-03-10 06:35:06 +08:00
srand ( time ( 0 ) ) ;
2019-03-09 15:59:13 +08:00
2019-05-01 05:52:40 +08:00
session . pm3_present = false ;
2019-05-02 02:48:15 +08:00
session . help_dump_mode = false ;
2019-03-10 06:35:06 +08:00
bool waitCOMPort = false ;
bool addLuaExec = false ;
2019-08-04 21:34:18 +08:00
bool stayInCommandLoop = false ;
2019-03-10 06:35:06 +08:00
char * script_cmds_file = NULL ;
char * script_cmd = NULL ;
2019-04-03 04:06:10 +08:00
char * port = NULL ;
uint32_t speed = 0 ;
2018-03-17 21:35:34 +08:00
2019-03-10 07:00:59 +08:00
/* initialize history */
2019-03-10 06:35:06 +08:00
using_history ( ) ;
2018-11-03 01:27:42 +08:00
2018-11-03 18:10:55 +08:00
# ifdef RL_STATE_READCMD
2019-03-10 06:35:06 +08:00
rl_extend_line_buffer ( 1024 ) ;
2018-11-03 18:10:55 +08:00
# endif
2019-03-09 15:59:13 +08:00
2019-04-14 19:35:52 +08:00
char * exec_name = argv [ 0 ] ;
2019-04-13 19:34:02 +08:00
# if defined(_WIN32)
2019-04-14 19:35:52 +08:00
for ( int m = strlen ( exec_name ) ; m > 0 ; m - - ) {
2019-04-14 19:37:53 +08:00
if ( exec_name [ m ] = = ' \\ ' ) {
2019-04-14 19:35:52 +08:00
exec_name + = ( + + m ) ;
2019-04-14 18:54:13 +08:00
break ;
2019-04-13 19:34:02 +08:00
}
2019-03-10 06:35:06 +08:00
}
2019-04-14 18:54:13 +08:00
# endif
2019-03-10 06:35:06 +08:00
2019-09-09 07:07:46 +08:00
bool flash_mode = false ;
bool flash_can_write_bl = false ;
int flash_num_files = 0 ;
char * flash_filenames [ FLASH_MAX_FILES ] ;
2019-09-13 02:13:01 +08:00
// set global variables soon enough to get the log path
set_my_executable_path ( ) ;
set_my_user_directory ( ) ;
2020-04-12 11:07:25 +08:00
# ifdef USE_PREFERENCE_FILE
2020-04-10 13:04:11 +08:00
// Load Settings and assign
// This will allow the command line to override the settings.json values
2020-04-16 15:01:14 +08:00
preferences_load ( ) ;
2020-04-12 11:07:25 +08:00
// Change height/width (Rows,Cols) - Testing
// printf ("\e[8;50;100t");
// printf ("\e[3;50;50t"); // x,y
//printf ("Path : %s \n",my_user_directory);
2020-04-10 13:04:11 +08:00
// quick patch for debug level
2020-04-10 16:20:02 +08:00
g_debugMode = session . client_debug_level ;
2020-04-06 14:36:12 +08:00
// settings_save ();
2020-04-05 18:36:39 +08:00
// End Settings
2020-04-10 17:51:08 +08:00
# endif
2020-04-10 14:14:43 +08:00
2019-04-14 19:37:53 +08:00
for ( int i = 1 ; i < argc ; i + + ) {
2019-03-10 06:35:06 +08:00
2019-04-14 18:54:13 +08:00
if ( argv [ i ] [ 0 ] ! = ' - ' ) {
// For backward compatibility we accept direct port
if ( port ! = NULL ) {
// We got already one
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( ERR , _RED_ ( " ERROR: " ) " cannot parse command line. We got " _YELLOW_ ( " %s " ) " as port and now we got also: " _YELLOW_ ( " %s " ) " \n " , port , argv [ i ] ) ;
2019-04-14 19:35:52 +08:00
show_help ( false , exec_name ) ;
2019-04-14 18:54:13 +08:00
return 1 ;
}
port = argv [ i ] ;
continue ;
}
// port
if ( strcmp ( argv [ i ] , " -p " ) = = 0 | | strcmp ( argv [ i ] , " --port " ) = = 0 ) {
if ( i + 1 = = argc ) {
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( ERR , _RED_ ( " ERROR: " ) " missing port specification after -p \n " ) ;
2019-04-14 19:35:52 +08:00
show_help ( false , exec_name ) ;
2019-04-14 18:54:13 +08:00
return 1 ;
}
if ( port ! = NULL ) {
// We got already one
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( ERR , _RED_ ( " ERROR: " ) " cannot parse command line. We got " _YELLOW_ ( " %s " ) " as port and now we got also: " _YELLOW_ ( " %s " ) " \n " , port , argv [ i + 1 ] ) ;
2019-04-14 19:35:52 +08:00
show_help ( false , exec_name ) ;
2019-04-14 18:54:13 +08:00
return 1 ;
}
port = argv [ + + i ] ;
continue ;
}
// short help
if ( strcmp ( argv [ i ] , " -h " ) = = 0 | | strcmp ( argv [ i ] , " --help " ) = = 0 ) {
2019-09-10 03:30:25 +08:00
g_printAndLog = PRINTANDLOG_PRINT ;
2019-04-14 19:35:52 +08:00
show_help ( true , exec_name ) ;
2019-04-14 18:54:13 +08:00
return 0 ;
}
// dump help
if ( strcmp ( argv [ i ] , " -t " ) = = 0 | | strcmp ( argv [ i ] , " --text " ) = = 0 ) {
2019-09-10 03:30:25 +08:00
g_printAndLog = PRINTANDLOG_PRINT ;
2019-04-14 19:35:52 +08:00
show_help ( false , exec_name ) ;
2019-03-10 06:35:06 +08:00
dumpAllHelp ( 0 ) ;
return 0 ;
}
// dump markup
2019-04-14 18:54:13 +08:00
if ( strcmp ( argv [ i ] , " -m " ) = = 0 | | strcmp ( argv [ i ] , " --markdown " ) = = 0 ) {
2019-09-10 03:30:25 +08:00
g_printAndLog = PRINTANDLOG_PRINT ;
2019-03-10 06:35:06 +08:00
dumpAllHelp ( 1 ) ;
return 0 ;
}
2019-09-10 02:45:10 +08:00
// print client version
2019-08-21 18:52:59 +08:00
if ( strcmp ( argv [ i ] , " -v " ) = = 0 | | strcmp ( argv [ i ] , " --version " ) = = 0 ) {
pm3_version ( true , true ) ;
return 0 ;
}
2019-09-10 02:45:10 +08:00
// set debugmode
if ( strcmp ( argv [ i ] , " -d " ) = = 0 | | strcmp ( argv [ i ] , " --debug " ) = = 0 ) {
if ( i + 1 = = argc ) {
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( ERR , _RED_ ( " ERROR: " ) " missing debugmode specification after -d \n " ) ;
2019-09-10 02:45:10 +08:00
show_help ( false , exec_name ) ;
return 1 ;
}
int demod = atoi ( argv [ i + 1 ] ) ;
if ( demod < 0 | | demod > 2 ) {
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( ERR , _RED_ ( " ERROR: " ) " invalid debugmode: -d " _YELLOW_ ( " %s " ) " \n " , argv [ i + 1 ] ) ;
2019-09-10 02:45:10 +08:00
return 1 ;
}
g_debugMode = demod ;
i + + ;
continue ;
}
2019-03-10 06:35:06 +08:00
// flush output
2019-04-14 18:54:13 +08:00
if ( strcmp ( argv [ i ] , " -f " ) = = 0 | | strcmp ( argv [ i ] , " --flush " ) = = 0 ) {
2019-03-10 06:35:06 +08:00
SetFlushAfterWrite ( true ) ;
PrintAndLogEx ( INFO , " Output will be flushed after every print. \n " ) ;
2019-04-03 04:06:10 +08:00
continue ;
}
// set baudrate
2019-04-14 18:54:13 +08:00
if ( strcmp ( argv [ i ] , " -b " ) = = 0 | | strcmp ( argv [ i ] , " --baud " ) = = 0 ) {
if ( i + 1 = = argc ) {
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( ERR , _RED_ ( " ERROR: " ) " missing baud specification after -b \n " ) ;
2019-04-14 19:35:52 +08:00
show_help ( false , exec_name ) ;
2019-04-14 18:54:13 +08:00
return 1 ;
}
2019-07-11 00:46:30 +08:00
uint64_t tmpspeed = strtoul ( argv [ i + 1 ] , NULL , 10 ) ;
2019-04-03 04:06:10 +08:00
if ( ( tmpspeed = = ULONG_MAX ) | | ( tmpspeed = = 0 ) ) {
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( ERR , _RED_ ( " ERROR: " ) " invalid baudrate: -b " _YELLOW_ ( " %s " ) " \n " , argv [ i + 1 ] ) ;
2019-04-03 04:06:10 +08:00
return 1 ;
}
speed = tmpspeed ;
i + + ;
continue ;
2019-03-10 06:35:06 +08:00
}
// wait for comport
2019-04-14 18:54:13 +08:00
if ( strcmp ( argv [ i ] , " -w " ) = = 0 | | strcmp ( argv [ i ] , " --wait " ) = = 0 ) {
2019-03-10 06:35:06 +08:00
waitCOMPort = true ;
2019-04-03 04:06:10 +08:00
continue ;
2019-03-10 06:35:06 +08:00
}
// execute pm3 command
2019-04-14 18:54:13 +08:00
if ( strcmp ( argv [ i ] , " -c " ) = = 0 | | strcmp ( argv [ i ] , " --command " ) = = 0 ) {
if ( i + 1 = = argc ) {
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( ERR , _RED_ ( " ERROR: " ) " missing command specification after -c \n " ) ;
2019-04-14 19:35:52 +08:00
show_help ( false , exec_name ) ;
2019-04-14 18:54:13 +08:00
return 1 ;
}
script_cmd = argv [ + + i ] ;
2019-04-03 04:06:10 +08:00
continue ;
2019-03-10 06:35:06 +08:00
}
2019-05-06 20:11:23 +08:00
// execute pm3 command file
2019-04-14 18:54:13 +08:00
if ( strcmp ( argv [ i ] , " -s " ) = = 0 | | strcmp ( argv [ i ] , " --script-file " ) = = 0 ) {
if ( i + 1 = = argc ) {
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( ERR , _RED_ ( " ERROR: " ) " missing script file specification after -s \n " ) ;
2019-04-14 19:35:52 +08:00
show_help ( false , exec_name ) ;
2019-04-14 18:54:13 +08:00
return 1 ;
}
script_cmds_file = argv [ + + i ] ;
2019-04-03 04:06:10 +08:00
continue ;
}
2019-04-14 18:54:13 +08:00
// execute lua script
if ( strcmp ( argv [ i ] , " -l " ) = = 0 | | strcmp ( argv [ i ] , " --lua " ) = = 0 ) {
addLuaExec = true ;
if ( i + 1 = = argc ) {
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( ERR , _RED_ ( " ERROR: " ) " missing lua script specification after -l \n " ) ;
2019-04-14 19:35:52 +08:00
show_help ( false , exec_name ) ;
2019-04-14 18:54:13 +08:00
return 1 ;
}
script_cmd = argv [ + + i ] ;
continue ;
2019-04-03 04:06:10 +08:00
}
2019-08-04 21:34:18 +08:00
// go to interactive instead of quitting after a script/command
2019-08-04 22:57:06 +08:00
if ( strcmp ( argv [ i ] , " -i " ) = = 0 | | strcmp ( argv [ i ] , " --interactive " ) = = 0 ) {
2019-08-04 21:34:18 +08:00
stayInCommandLoop = true ;
continue ;
}
2019-09-09 07:07:46 +08:00
// go to flash mode
if ( strcmp ( argv [ i ] , " --flash " ) = = 0 ) {
flash_mode = true ;
continue ;
}
// unlock bootloader area
if ( strcmp ( argv [ i ] , " --unlock-bootloader " ) = = 0 ) {
flash_can_write_bl = true ;
continue ;
}
// flash file
if ( strcmp ( argv [ i ] , " --image " ) = = 0 ) {
if ( flash_num_files = = FLASH_MAX_FILES ) {
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( ERR , _RED_ ( " ERROR: " ) " too many --image, please use it max %i times \n " , FLASH_MAX_FILES ) ;
2019-09-09 07:07:46 +08:00
return 1 ;
}
if ( i + 1 = = argc ) {
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( ERR , _RED_ ( " ERROR: " ) " missing image specification after --image \n " ) ;
2019-09-09 07:07:46 +08:00
show_help ( false , exec_name ) ;
return 1 ;
}
flash_filenames [ flash_num_files + + ] = argv [ + + i ] ;
continue ;
}
2019-04-14 18:54:13 +08:00
// We got an unknown parameter
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( ERR , _RED_ ( " ERROR: " ) " invalid parameter: " _YELLOW_ ( " %s " ) " \n " , argv [ i ] ) ;
2019-04-14 19:35:52 +08:00
show_help ( false , exec_name ) ;
2019-04-14 18:54:13 +08:00
return 1 ;
2019-03-10 06:35:06 +08:00
}
2020-04-12 11:07:25 +08:00
# ifndef USE_PREFERENCE_FILE
2020-04-16 15:01:14 +08:00
// comment next 2 lines to use session values set from settings_load
2019-10-16 20:46:57 +08:00
session . supports_colors = DetectWindowsAnsiSupport ( ) ;
2020-03-16 05:41:05 +08:00
session . emoji_mode = ALTTEXT ;
2020-04-10 17:51:08 +08:00
# endif
2019-10-05 12:09:46 +08:00
2019-04-30 19:02:27 +08:00
session . stdinOnTTY = isatty ( STDIN_FILENO ) ;
session . stdoutOnTTY = isatty ( STDOUT_FILENO ) ;
# if defined(__linux__) || (__APPLE__)
// it's okay to use color if:
// * Linux or OSX
// * Not redirected to a file but printed to term
// For info, grep --color=auto is doing sth like this, plus test getenv("TERM") != "dumb":
// struct stat tmp_stat;
// if ((fstat (STDOUT_FILENO, &tmp_stat) == 0) && (S_ISCHR (tmp_stat.st_mode)) && isatty(STDIN_FILENO))
2020-04-12 17:49:17 +08:00
# ifdef USE_PREFERENCE_FILE
2020-04-16 15:01:14 +08:00
if ( ! session . preferences_loaded ) {
if ( session . stdinOnTTY & & session . stdoutOnTTY ) {
session . supports_colors = true ;
session . emoji_mode = EMOJI ;
2020-04-12 17:49:17 +08:00
}
2020-04-16 15:01:14 +08:00
}
2020-04-12 17:49:17 +08:00
# else
2020-03-16 05:41:05 +08:00
if ( session . stdinOnTTY & & session . stdoutOnTTY ) {
2019-04-30 19:02:27 +08:00
session . supports_colors = true ;
2020-03-16 05:41:05 +08:00
session . emoji_mode = EMOJI ;
}
2020-04-12 17:49:17 +08:00
# endif
2019-04-30 19:02:27 +08:00
# endif
2019-04-29 04:51:40 +08:00
// Let's take a baudrate ok for real UART, USB-CDC & BT don't use that info anyway
2019-04-03 04:06:10 +08:00
if ( speed = = 0 )
2019-04-21 01:17:32 +08:00
speed = USART_BAUD_RATE ;
2019-04-03 04:06:10 +08:00
2019-09-09 07:07:46 +08:00
if ( flash_mode ) {
flash_pm3 ( port , flash_num_files , flash_filenames , flash_can_write_bl ) ;
exit ( EXIT_SUCCESS ) ;
}
2019-04-14 18:54:13 +08:00
if ( script_cmd ) {
while ( script_cmd [ strlen ( script_cmd ) - 1 ] = = ' ' )
script_cmd [ strlen ( script_cmd ) - 1 ] = 0x00 ;
2019-03-10 06:35:06 +08:00
2019-04-14 18:54:13 +08:00
if ( strlen ( script_cmd ) = = 0 ) {
script_cmd = NULL ;
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( ERR , _RED_ ( " ERROR: " ) " execute command: " _YELLOW_ ( " command not found " ) " . \n " ) ;
2019-04-14 18:54:13 +08:00
return 2 ;
} else {
if ( addLuaExec ) {
// add "script run " to command
int len = strlen ( script_cmd ) + 11 + 1 ;
char * ctmp = ( char * ) calloc ( len , sizeof ( uint8_t ) ) ;
if ( ctmp ! = NULL ) {
memset ( ctmp , 0 , len ) ;
strcpy ( ctmp , " script run " ) ;
strcpy ( & ctmp [ 11 ] , script_cmd ) ;
script_cmd = ctmp ;
2019-03-10 06:35:06 +08:00
}
}
2019-04-16 23:29:19 +08:00
PrintAndLogEx ( SUCCESS , " execute command from commandline: " _YELLOW_ ( " %s " ) " \n " , script_cmd ) ;
2019-04-14 18:54:13 +08:00
}
2019-03-10 06:35:06 +08:00
}
2017-10-22 17:05:25 +08:00
2019-03-10 06:35:06 +08:00
// try to open USB connection to Proxmark
2019-05-07 23:31:07 +08:00
if ( port ! = NULL ) {
2019-05-08 02:37:23 +08:00
OpenProxmark ( port , waitCOMPort , 20 , false , speed ) ;
2019-05-07 23:31:07 +08:00
}
2019-04-14 18:54:13 +08:00
2019-05-01 05:52:40 +08:00
if ( session . pm3_present & & ( TestProxmark ( ) ! = PM3_SUCCESS ) ) {
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( ERR , _RED_ ( " ERROR: " ) " cannot communicate with the Proxmark \n " ) ;
2019-04-27 08:46:20 +08:00
CloseProxmark ( ) ;
}
2019-05-06 04:04:35 +08:00
2019-07-18 02:15:47 +08:00
if ( ( port ! = NULL ) & & ( ! session . pm3_present ) )
exit ( EXIT_FAILURE ) ;
2019-05-01 05:52:40 +08:00
if ( ! session . pm3_present )
2020-04-22 08:22:55 +08:00
PrintAndLogEx ( INFO , " Running in " _YELLOW_ ( " OFFLINE " ) " mode. Check " _YELLOW_ ( " \" %s -h \" " ) " if it's not what you want. \n " , exec_name ) ;
Client cleanup and restructuring. Stage 1...
Next Step is refactoring some of the giant functions which are
just copy/paste of some other ones with just a few line changes,
removing unnecessary 'goto' etc.
The MS Windows version is broken with this commit but will be fixed
soon. Everything can't be done all at once :P
The commands are now hierarchical, for example:
"hf 14a read" vs. "hf 14b read".
You can also request help:
"hf help", "data help", "hf 15 help" etc.
Indents are now space-based, not tab-based anymore. Hopefully
no one will be trolling about it, considering the suicide-prone work
being done here ;)
client/cmdhw.c, client/proxusb.c, client/cmdhw.h, client/proxusb.h,
client/cmdmain.c, client/cmdlfhid.c, client/cmdmain.h, client/cmdlfhid.h,
client/data.c, client/data.h, client/cmdhf.c, client/cmdlf.c,
client/cmdhf.h, client/cmdhf15.c, client/cmdhf14b.c, client/cmdlf.h,
client/cmdhf15.h, client/cmdhf14b.h, client/cmddata.c, client/cmddata.h,
client/ui.c, client/cmdparser.c, client/cmdlfti.c, client/ui.h,
client/cmdlfem4x.c, client/cmdparser.h, client/cmdlfti.h, client/cmdlfem4x.h,
client/graph.c, client/graph.h, client/cmdhf14a.c, client/cmdhf14a.h,
client/cmdhflegic.c, client/cmdhflegic.c: New files.
client/cli.c, client/flasher.c, client/snooper.c, client/proxmark3.c,
client/proxmark3.h, client/Makefile: Update accordingly.
client/flash.h, client/flash.c, client/proxgui.cpp: Cosmetic changes.
client/translate.h, client/command.c, client/gui.c,
client/usb.c, client/prox.h: Remove.
include/usb_cmd.h (CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM): Remove dead cmd.
common/crc16.h: New file.
common/crc16.c: Modify accordingly.
common/iso14443crc.h: New file.
common/iso14443_crc.c: Rename to
common/iso14443crc.c: and modify accordingly.
armsrc/lfops.c, armsrc/iso14443.c,
armsrc/iso14443a.c: include .h files from
the common directory instead of including the c files.
common/Makefile.common, armsrc/Makefile: Modify accordingly.
2010-02-04 09:27:07 +08:00
2020-01-05 02:59:36 +08:00
// ascii art only in interactive client
if ( ! script_cmds_file & & ! script_cmd & & session . stdinOnTTY & & session . stdoutOnTTY & & ! flash_mode )
showBanner ( ) ;
2020-04-12 11:07:25 +08:00
# ifdef USE_PREFERENCE_FILE
2020-04-12 18:24:56 +08:00
// Save settings if not loaded from settings json file.
2020-04-10 17:51:08 +08:00
// Doing this here will ensure other checks and updates are saved to over rule default
// e.g. Linux color use check
2020-04-12 17:49:17 +08:00
if ( ! session . preferences_loaded ) {
2020-04-16 15:01:14 +08:00
preferences_save ( ) ; // Save defaults
2020-04-12 17:49:17 +08:00
session . preferences_loaded = true ;
}
2020-04-10 17:51:08 +08:00
# endif
2017-07-28 03:32:15 +08:00
# ifdef HAVE_GUI
2017-08-27 14:50:55 +08:00
2017-10-18 02:58:17 +08:00
# ifdef _WIN32
2019-08-04 21:34:18 +08:00
InitGraphics ( argc , argv , script_cmds_file , script_cmd , stayInCommandLoop ) ;
2019-03-10 06:35:06 +08:00
MainGraphics ( ) ;
2017-08-27 14:50:55 +08:00
# else
2019-03-10 06:35:06 +08:00
// for *nix distro's, check enviroment variable to verify a display
2019-03-10 07:00:59 +08:00
char * display = getenv ( " DISPLAY " ) ;
2019-03-10 06:35:06 +08:00
if ( display & & strlen ( display ) > 1 ) {
2019-08-04 21:34:18 +08:00
InitGraphics ( argc , argv , script_cmds_file , script_cmd , stayInCommandLoop ) ;
2019-03-10 06:35:06 +08:00
MainGraphics ( ) ;
} else {
2019-08-04 21:34:18 +08:00
main_loop ( script_cmds_file , script_cmd , stayInCommandLoop ) ;
2019-03-10 06:35:06 +08:00
}
2017-08-27 14:50:55 +08:00
# endif
2019-03-09 15:59:13 +08:00
2017-07-28 03:32:15 +08:00
# else
2019-08-04 21:34:18 +08:00
main_loop ( script_cmds_file , script_cmd , stayInCommandLoop ) ;
2019-03-09 15:59:13 +08:00
# endif
2019-03-10 06:35:06 +08:00
// Clean up the port
2019-05-01 05:52:40 +08:00
if ( session . pm3_present ) {
2019-03-10 06:35:06 +08:00
CloseProxmark ( ) ;
}
2019-03-09 15:59:13 +08:00
2020-04-13 11:51:03 +08:00
# ifdef USE_PREFERENCE_FILE
2020-04-13 14:17:57 +08:00
if ( session . window_changed ) // Plot/Overlay moved or resized
2020-04-16 15:01:14 +08:00
preferences_save ( ) ;
2020-04-13 11:51:03 +08:00
# endif
2019-07-18 02:15:47 +08:00
exit ( EXIT_SUCCESS ) ;
2019-03-06 04:14:30 +08:00
}