我的小工具-远程读卡器web客户端(PHP+LUA)
来源:互联网 发布:实时对话翻译软件 编辑:程序博客网 时间:2024/06/10 17:31
本工具是在浏览器中以Lua脚本的形式对CPU卡,M1卡就行读、写等各种操作,配和使用改造过后的E711读卡器。 远端把读卡器接到电脑上,并运行读写卡服务。告知客户端IP地址和端口,并放上卡。客户端调用相关指令,运行脚本,输出结果。
远程读卡器就是一个普通usb口或串口的读卡器,如E711读卡器。配合一个电脑软件作为tcp读写卡服务。这样可以在公司电脑上运行客户端程序连到服务器上,服务器端操控现场的读卡器。之前做保定公交老卡兼容,让现场寄卡过来,结果拖了好久,卡也没寄过来。说是卡片管理严格,老年卡,学生卡需要从系统上从新办卡。于是让现场同事配合抓下包,读取一下卡上数据,但现场同事连串口助手都没听说过,指望不上了。最后没办法,还是出差跑去一趟,做了些很简单的事。回来想想,其实可以做一个远程读卡器,在公司把现场的卡给操作了。再封装一些读卡的客户端接口,可以实现远程仿真调试程序读卡消费逻辑 ,或者实现一完全软件模拟的pos机。之前用java做过一个读写卡工具,但是只能在本地电脑上读写卡。
要远程读写卡得有个后台服务去操控远程的读卡器。有了后台读写卡服务,客户端不能只是接口,得简单好用,于是有了这个web端。
附截图:
截图1,运行效果
截图2,相关指令介绍:
截图3,后台文件
截图4,后台读写卡服务显示的收发日志:
后台的解析lua脚本的文件lua_test.c
//包含LUA的头文件,用来支持脚本#include <stdio.h>#include "lib/lua-5.3.1/lua.h" #include "lib/lua-5.3.1/lualib.h" #include "lib/lua-5.3.1/lauxlib.h" #include "lib/includes.h"#define PICC_ADD 0xC1 //加#define PICC_SUB 0xC0 //减#define PICC_RESTORE 0xC2 //恢复#define PICC_KEYA 0x60 //KEY A#define PICC_KEYB 0x61 //KEY B#define PICC_NULL 0x00 //不校验KEYlua_State* L; U08 gCardSN[8]; //物理卡号U32 ICF_SelectAID( const char *AID, U32 ilen, U32 ich ){ U32 rcode; gCmdBuffer[0] = 0x00; //CLA gCmdBuffer[1] = 0xA4; //INS gCmdBuffer[2] = 0x04; //P1 gCmdBuffer[3] = 0x00; //P2 gCmdBuffer[4] = ilen; //Lc CurCalc_DataCpy( gCmdBuffer+5, (U08*)AID, ilen ); rcode = ICC_APDU_Exchange( ich, gCmdBuffer, ilen+5, gpRcvBuffer, &Grcv_Len, 260 ); if( rcode != 0 ) { return rcode; } if( Grcv_Len < 2 ) { return 2;} rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] ); return rcode;}U32 ICF_SelectSFI( const char *SFI, U32 ich ){ U32 rcode; gCmdBuffer[0] = 0x00; //CLA gCmdBuffer[1] = 0xA4; //INS gCmdBuffer[2] = 0x00; //P1 gCmdBuffer[3] = 0x00; //P2 gCmdBuffer[4] = 0x02; //Lc CurCalc_DataCpy( gCmdBuffer+5, (U08*)SFI, 2 ); rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 2+5, gpRcvBuffer, &Grcv_Len, 260 ); if( rcode != 0 ) { return rcode; } if( Grcv_Len < 2 ) { return 2;} rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] ); return rcode;}U32 ICF_ReadBinaryFile( U08 SFI, U08 Offset, U08 BytesToRead, U32 ich ){ unsigned short rcode; gCmdBuffer[0] = 0x00; //CLA gCmdBuffer[1] = 0xB0; //INS gCmdBuffer[2] = 0x80 | ( SFI & 0x1F ); //P1 gCmdBuffer[3] = Offset; //P2 gCmdBuffer[4] = BytesToRead; //Le rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 5, gpRcvBuffer, &Grcv_Len, 260 ); if( rcode != 0 ) { return rcode; } if( Grcv_Len < 2 ) //长度判断 { return 2;} rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] ); return rcode;}int LConnect(lua_State* L){ int ret = 0; size_t le = 0; printf("Connecting...\n"); const char * ipaddr = luaL_checklstring(L,1,&le); //printf("cmd is %s,le is %d\n",aid,le); //从L栈中取出索引为2的数值,并检查 int port = luaL_checkinteger(L,2); printf("ServerIP:%s,Port:%d\n", ipaddr,port); ret = Connect(ipaddr,port); lua_pushnumber(L,ret); return 1;}int LDisConnect(lua_State* L){ printf("Close connect!\n"); Com_Dev_Disconnect( 0 ); return 1;}int LTxData(lua_State* L){ int ret = 0; unsigned int len = 0; size_t le = 0; unsigned char buf[1024]; unsigned char outbuf[2048]; memset(buf, 0, 1024); memset(outbuf, 0, 2048); //从L栈中取出索引为1的数值,并检查 const char * txdata = luaL_checklstring(L,1,&le); //printf("tx is %s,le is %d\n",txdata,le); StrToHex( (char*)txdata, le, buf ); ret = Com_Dev_TxData( buf, le/2, 0, 0 );if( ret != 0 ){ DEF_SysCard_Debug; return ret; } ret = Com_Dev_RxData( buf, &len, 1024, 0, 0 ); if( ret != 0 ){ DEF_SysCard_Debug; return ret; }HexToStr(buf,len,(char*)outbuf); lua_pushinteger(L,ret); lua_pushlstring(L,(char*)outbuf,strlen((char*)outbuf)); return 2;}int LTxData1(lua_State* L){ int ret = 0; unsigned int len = 0; size_t le = 0; unsigned char buf[1024]; unsigned char outbuf[2048]; memset(buf, 0, 1024); memset(outbuf, 0, 2048); //从L栈中取出索引为1的数值,并检查 const char * txdata = luaL_checklstring(L,1,&le); // printf("tx is %s,le is %d\n",txdata,le); //StrToHex( (char*)txdata, le, buf ); ret = Com_Dev_TxData1( (unsigned char*)txdata, le, 0, 0 );if( ret != 0 ){ DEF_SysCard_Debug; return ret; } ret = Com_Dev_RxData1( buf, &len, 1024, 0, 0 ); if( ret != 0 ){ DEF_SysCard_Debug; return ret; }//HexToStr(buf,len,(char*)outbuf); lua_pushinteger(L,ret); lua_pushlstring(L,(char*)buf,len); return 2;}int LAPDU_Exchange(lua_State* L){int ret = 0; size_t le = 0; unsigned char buf[520];memset(buf, 0, 520); //从L栈中取出索引为1的数值,并检查 const char * cmd = luaL_checklstring(L,1,&le); //printf("cmd is %s,le is %d\n",aid,le); //从L栈中取出索引为2的数值,并检查 int ich = luaL_checkinteger(L,2); StrToHex( (char*)cmd, le, gCmdBuffer ); ret = ICC_APDU_Exchange( ich, gCmdBuffer, le/2, gpRcvBuffer, &Grcv_Len, 260 ); if( Grcv_Len < 2){ return 1;} ret = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] ); HexToStr(gpRcvBuffer,Grcv_Len,(char*)buf); lua_pushinteger(L,ret); lua_pushlstring(L,(char*)buf,strlen((char*)buf)); return 2;}int LSelectAID(lua_State* L){ int ret = 0; size_t le = 0; unsigned char buf[520]; memset(buf, 0, 520); //从L栈中取出索引为1的数值,并检查 const char * aid = luaL_checklstring(L,1,&le); //printf("aid is %s,le is %d\n",aid,le); //从L栈中取出索引为2的数值,并检查 int len = luaL_checkinteger(L,2); int ich = luaL_checkinteger(L,3); ret = ICF_SelectAID( aid, len, ich ); HexToStr(gpRcvBuffer,Grcv_Len,(char*)buf); lua_pushinteger(L,ret); lua_pushlstring(L,(char*)buf,strlen((char*)buf)); return 2;}int LSelectSFI(lua_State* L){ int ret = 0; size_t le = 0; unsigned char buf[520]; memset(buf, 0, 520); //从L栈中取出索引为1的数值,并检查 const char * sfi = luaL_checklstring(L,1,&le); //printf("aid is %s,le is %d\n",aid,le); //从L栈中取出索引为2的数值,并检查 int ich = luaL_checkinteger(L,2); ret = ICF_SelectSFI( sfi, ich ); HexToStr(gpRcvBuffer,Grcv_Len,(char*)buf); lua_pushinteger(L,ret); lua_pushlstring(L,(char*)buf,strlen((char*)buf)); return 2;}int LReadBinaryFile( lua_State* L ){ int ret = 0; unsigned char buf[520]; memset(buf, 0, 520); //从L栈中取出索引为1的数值,并检查 int sfi = luaL_checkinteger(L,1); int oft = luaL_checkinteger(L,2); int rlen = luaL_checkinteger(L,3); int ich = luaL_checkinteger(L,4); ret = ICF_ReadBinaryFile(sfi,oft,rlen,ich); HexToStr(gpRcvBuffer,Grcv_Len,(char*)buf); lua_pushinteger(L,ret); lua_pushlstring(L,(char*)buf,strlen((char*)buf)); //stackDump(L); return 2;}//获取CPU或M1卡的物理卡号int LGetPhySn( lua_State* L ){ int ret = 0; unsigned char buf[20]; unsigned char buf1[20]; memset(buf,0,20); memset(buf1,0,20); ret = ICC_MiOne_GetPhySn(buf); memcpy(gCardSN,buf,8);//保存全局物理卡号 HexToStr(buf,8,(char*)buf1); lua_pushinteger(L,ret); lua_pushlstring(L,(char*)buf1,strlen((char*)buf1)); //stackDump(L); return 2;}//M1卡扇区读int LBlkRead( lua_State* L ){ int ret = 0; size_t le = 0; unsigned char rbuf[50]; unsigned char sbuf[50]; unsigned char key[16]; unsigned char cmd=0; int block = luaL_checkinteger(L,1); const char * keys = luaL_checklstring(L,2,&le); int keytype = luaL_checkinteger(L,3); //密码类型,0,不校验 1,A码,2,B码 memset(rbuf,0,50); memset(sbuf,0,50); StrToHex( (char*)keys, le, key ); cmd = PICC_KEYA; if(keytype == 1) { cmd = PICC_KEYA; } else if(keytype == 2) { cmd = PICC_KEYB; } ret = ICC_MiOne_BlkRead(block,cmd,key, gCardSN, rbuf ); HexToStr(rbuf,16,(char*)sbuf); lua_pushinteger(L,ret); lua_pushlstring(L,(char*)sbuf,strlen((char*)sbuf)); //stackDump(L); return 2;}//M1卡扇区写int LBlkWrite( lua_State* L ){ int ret = 0; size_t le = 0,le1 =0; unsigned char wbuf[50]; unsigned char key[16]; unsigned char cmd=0; int block = luaL_checkinteger(L,1); const char * wbufs = luaL_checklstring(L,2,&le); const char * keys = luaL_checklstring(L,3,&le1); int keytype = luaL_checkinteger(L,4); //密码类型,0,不校验 1,A码,2,B码 memset(wbuf,0,50); StrToHex( (char*)wbufs, le, wbuf ); StrToHex( (char*)keys, le1, key ); cmd = PICC_KEYA; if(keytype == 1) { cmd = PICC_KEYA; } else if(keytype == 2) { cmd = PICC_KEYB; } ret = ICC_MiOne_BlkWrite(block,cmd,key, gCardSN, wbuf ); lua_pushinteger(L,ret); //stackDump(L); return 1;}//DES加密int LDES_Encrypt( lua_State* L ){ // int ret = 0; size_t le = 0,le1 =0; unsigned char inkey[16]; unsigned char indata[16]; unsigned char outdata[16];unsigned char str_out[50]; const char * str_inkey = luaL_checklstring(L,1,&le); const char * str_indata = luaL_checklstring(L,2,&le1); StrToHex( (char*)str_inkey, le, inkey ); StrToHex( (char*)str_indata, le1, indata );CurCalc_DES_Encrypt( inkey, indata, outdata );HexToStr(outdata,8,(char*)str_out); //lua_pushinteger(L,ret); lua_pushlstring(L,(char*)str_out,16); //stackDump(L); return 1;}//DES解密int LDES_Decrypt( lua_State* L ){ // int ret = 0; size_t le = 0,le1 =0; unsigned char inkey[16]; unsigned char indata[16]; unsigned char outdata[16];unsigned char str_out[50]; const char * str_inkey = luaL_checklstring(L,1,&le); const char * str_indata = luaL_checklstring(L,2,&le1); StrToHex( (char*)str_inkey, le, inkey ); StrToHex( (char*)str_indata, le1, indata );CurCalc_DES_Decrypt( inkey, indata, outdata );HexToStr(outdata,8,(char*)str_out); //lua_pushinteger(L,ret); lua_pushlstring(L,(char*)str_out,16); //stackDump(L); return 1;}//3DES加密int LDES_3Encrypt( lua_State* L ){ // int ret = 0; size_t le = 0,le1 =0; unsigned char inkey[16]; unsigned char indata[16]; unsigned char outdata[16];unsigned char str_out[50]; const char * str_inkey = luaL_checklstring(L,1,&le); const char * str_indata = luaL_checklstring(L,2,&le1); StrToHex( (char*)str_inkey, le, inkey ); StrToHex( (char*)str_indata, le1, indata );CurCalc_3DES_Encrypt( inkey, indata, outdata );HexToStr(outdata,16,(char*)str_out); //lua_pushinteger(L,ret); lua_pushlstring(L,(char*)str_out,32); //stackDump(L); return 1;}//3DES解密int LDES_3Decrypt( lua_State* L ){ // int ret = 0; size_t le = 0,le1 =0; unsigned char inkey[16]; unsigned char indata[16]; unsigned char outdata[16];unsigned char str_out[50]; const char * str_inkey = luaL_checklstring(L,1,&le); const char * str_indata = luaL_checklstring(L,2,&le1); StrToHex( (char*)str_inkey, le, inkey ); StrToHex( (char*)str_indata, le1, indata );CurCalc_3DES_Decrypt( inkey, indata, outdata );HexToStr(outdata,16,(char*)str_out); //lua_pushinteger(L,ret); lua_pushlstring(L,(char*)str_out,32); //stackDump(L); return 1;}U32 MathDesMac( U08 *pbuf, U32 length, U08 *key,U08 checktype ){U32 len ;U08 mac[8], mac1[8];len = length ;if( checktype == 0 ){CurCalc_DES_MAC64( (SINGLE_DES_ENCRYPTION|ZERO_CBC_IV), key, 0, pbuf, len , mac );memcpy( pbuf+len, mac, 8 );return 0 ;}else{//暂存源校验码memcpy( mac1, pbuf+len-8, 8 ) ; CurCalc_DES_MAC64( (SINGLE_DES_ENCRYPTION|ZERO_CBC_IV), key, 0, pbuf, len-8 , mac) ; if ( memcmp( mac, mac1, 8 ) == 0x00 ){return 0 ; //校验产生的校验码和原校验码相等, 校验成功}else{return 1 ; //校验产生的校验码和原校验码不等, 校验失败}}}int LMathDesMac( lua_State* L ){ int ret = 0; size_t le = 0,le1 =0; unsigned char inkey[16]; unsigned char indata[1024];unsigned char str_out[2048]; const char * str_indata = luaL_checklstring(L,1,&le);int inlen = luaL_checkinteger(L,2);const char * str_inkey = luaL_checklstring(L,3,&le1);int type = luaL_checkinteger(L,4); StrToHex( (char*)str_indata, le, indata );StrToHex( (char*)str_inkey, le1, inkey );ret = MathDesMac( indata, inlen,inkey,type );memset(str_out,0,2048);HexToStr(indata,inlen+8,(char*)str_out); lua_pushinteger(L,ret); lua_pushlstring(L,(char*)str_out,strlen((char*)str_out)); //stackDump(L); return 1;}int main( void ) { //初始化全局L L = luaL_newstate(); //创建lua的栈 //打开库 luaL_openlibs(L); //把函数压入栈中 //lua_pushcfunction(L, add); //设置全局ADD //lua_setglobal(L, "ADD"); //lua_register(L,"ADD",add); lua_pushcfunction(L, LConnect); //设置全局ADD lua_setglobal(L, "CONNECT"); lua_register(L,"DISCONNECT", LDisConnect); lua_register(L,"TxData",LTxData);lua_register(L,"TxData1",LTxData1); lua_register(L,"APDU", LAPDU_Exchange); lua_register(L,"S_AID",LSelectAID); lua_register(L,"S_SFI",LSelectSFI); lua_register(L,"R_BFile",LReadBinaryFile); lua_register(L,"G_SN",LGetPhySn); lua_register(L,"R_Block",LBlkRead); lua_register(L,"W_Block",LBlkWrite);lua_register(L,"DES_Enc",LDES_Encrypt); lua_register(L,"DES_Dec",LDES_Decrypt);lua_register(L,"DES_3Enc",LDES_3Encrypt); lua_register(L,"DES_3Dec",LDES_3Decrypt);lua_register(L,"MathDesMac",LMathDesMac); //加载我们的lua脚本文件 if(luaL_loadfile(L,"test.lua")) //载入lua脚本,是通过fopen打开的, { printf("error,failed to analysis script!\nmaybe syntax error!\n"); } //安全检查 lua_pcall(L,0,0,0); //这个函数会执行lua脚本 //push进lua函数 // lua_getglobal(L, "mylua1"); // lua_pcall(L,0,0,0); printf("end my lua script,finish!\n"); lua_close(L); //关闭lua的栈 return 0; }
php后台的处理原理:
compile.php
<?phpheader('Content-Type:json; charset=UTF-8');set_time_limit(0);//var_dump($_POST);$str= $_POST['code'];//echo $str;file_put_contents("test.lua",$str);$flv_cmd="lua_test.exe >out.txt";exec($flv_cmd);if(file_exists("out.txt")){$txt1 = file_get_contents("out.txt");$err ="ok";$txt =iconv("GB2312","UTF-8//IGNORE",$txt1); //将编码从GB2312转成UTF-8//echo $txt; }else{$txt ="output err!\n";$err ="exec err!\n";}$json = array("output"=>$txt,"langid"=>"17","code"=>"print(\"Hello World!\")","errors"=>$err,"time"=>"01\n");//var_dump($json);$result = json_encode($json);//var_dump($result);$output = $result;echo $output; ?>
--192.168.157.135/test3/runcode.php--读卡服务地址ip= "192.168.157.135"--读卡服务端口port = 5050--连接到读卡服务ret = CONNECT(ip,port) --建立连接------------------------------------------- CPU卡操作ret,rcv = S_SFI("\x3F\x00",1) --选择PSAM卡应用3F00ret,rcv = R_BFile(0x15,0,0,1) --读取PSAM卡15文件ret,rcv = R_BFile(0x16,0,0,1) --读取PSAM卡16文件if ret == 0x9000 thenPasmTID = string.sub(rcv,1,12)print("pasmTID:"..PasmTID)endret,rcv = S_AID("\xA0\x00\x00\x06\x32\x01\x01\x05",0x08,0) --选择交通部应用ret,rcv = R_BFile(0x15,0,0,0) --读取卡片0x15文件if ret == 0x9000 thenMakeCardId = string.sub(rcv,1,16)CardASN = string.sub(rcv,25,25+16-1)print(rcv)print("MakeCardId:"..MakeCardId)print("CardASN:"..CardASN)endret,rcv = R_BFile(0x16,0,0,0)ret,rcv = R_BFile(0x17,0,0,0) ret,rcv = S_SFI("\x80\x11",1) --选择交通部PSAM卡应用ret,rcv = APDU("805C030204",0) --读取余额--消费初始化cmd = '805001020B'index = '01'money = '00000001'cmdstr = cmd..index..money..PasmTIDprint("xiao fei chu shi hua:")ret,rcv = APDU(cmdstr,0) --消费初始化if ret == 0x9000 thenPullCTC = string.sub(rcv,9,9+4-1) --脱机交易序号KeyVer = string.sub(rcv,19,19+2-1)KeyDrk = string.sub(rcv,21,21+2-1)Icc = string.sub(rcv,23,23+8-1) --随机数print("PullCTC:"..PullCTC)print("KeyVer:"..KeyVer)print("KeyDrk:"..KeyDrk)print("Icc:"..Icc)endcmd = '8070000024'time ='20161128170231'cmdstr = cmd..Icc..PullCTC..money..'06'..time..KeyVer..KeyDrk..CardASN..MakeCardId ret,rcv = APDU(cmdstr,1) --PSAM卡算MACif ret == 0x9000 thenTTC = string.sub(rcv,1,8) --脱机交易序号MAC1 = string.sub(rcv,9,9+8-1)print("TTC:"..TTC)print("MAC1:"..MAC1)endcmd = '805401000F'cmdstr = cmd..TTC..time..MAC1ret,rcv = APDU(cmdstr,0)DISCONNECT() --断开连接
后台库文件的makefile:
########################################
#makefile
########################################
#编译主程序
BINARY := lua_test
OBJ_DIR :=
CC= gcc
LD= ld
CFLAGS= -std=c99 -Wall -g
LDSCRIPT= -lmycom -lws2_32 -liconv -lmyfile -lmycard -lmyup -lmycalc -lmyblkfile -llua
LDFLAGS= -Llib
SRC = $(wildcard *.c)
DIR = $(notdir $(SRC))
OBJS = $(patsubst %.c,$(OBJ_DIR)%.o,$(DIR))
#OBJS= main.o myutils.o inirw.o cmdpboc.o cputest.o bustcp.o ansrec.o m1cmd.o m1api.o m1test.o upcash.o myother.o getsys.o
#CFLAGS=-std=c99
#@echo Building lib...
#$(call make_subdir)
.PHONY: clean lib
all: prebuild $(BINARY).exe
prebuild:
@echo Building app...
$(BINARY).exe : $(OBJS)
@echo Generating ...
$(CC) -o $(BINARY).exe $(OBJS) $(LDFLAGS) $(LDSCRIPT)
@echo OK!
$(OBJ_DIR)%.o : %.c
$(CC) -c $(CFLAGS) $< -o $@
clean:
rm -f $(OBJ_DIR)*.o
@echo Removed!
- 我的小工具-远程读卡器web客户端(PHP+LUA)
- 我的小工具-远程读卡器web客户端(nodejs+websocket实现实时指令交互)
- 我的常用小工具
- 一个远程系统控制台的小工具
- 远程调试Python进程的小工具
- 远程执行小工具
- 我的常用小工具集
- 我开发的一个端口映射小工具
- 01-教你写一个web远程控制小工具
- Web开发常用的几个小工具
- web小工具
- 发个json文件转lua的小工具
- python版php web后门查杀小工具
- HTTP客户端+服务端小工具
- windows远程连接Linux的两个小工具
- WEB CC 测试小工具
- web 链接测试小工具
- WEB前端开发小工具
- Android SDK manager里面什么是必须下载的
- ajax 跨域
- 2017上半年总结
- 《做开发十年,我总结出了这些开发经验》读后感
- PHP运行底层原理
- 我的小工具-远程读卡器web客户端(PHP+LUA)
- python学习日志--day4
- group by 合并字符串
- Android RecyclerView 多布局与混排
- geometry-api-java 学习笔记(四)多线段 polyline
- PHP 生成token 示例
- 【Linux基础】进程和线程的区别
- Gitlab 隐藏注册功能
- 浅谈CSS属性之布局--flex布局<弹性盒模型>