/****************************************************************************************
* CANopenSocket CANopenCGI.c hacking
* 说明:
* 分析一下CANopenSocket中的CANopenCGI部分是怎么工作的。
*
* 2017-3-23 深圳 南山平山村 曾剑锋
***************************************************************************************/ /*
* Client socket command interface (Apache CGI) for CANopenSocket.
*
* @file CANopenCGI.c
* @author Janez Paternoster
* @copyright 2016 Janez Paternoster
*
* This file is part of CANopenNode, an opensource CANopen Stack.
* Project home page is <https://github.com/CANopenNode/CANopenNode>.
* For more information on CANopen see <http://www.can-cia.org/>.
*
* CANopenNode is free and open source 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 2 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, see <http://www.gnu.org/licenses/>.
*/ #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <fnmatch.h>
#include <sys/un.h>
#include <sys/socket.h> #ifndef BUF_SIZE
#define BUF_SIZE 100000
#endif /* Helper functions */
static void errExitErrno(char* msg) {
printf("%s: %s\n", msg, strerror(errno));
exit(EXIT_FAILURE);
} static void errExit(char* msg) {
printf("%s\n", msg);
exit(EXIT_FAILURE);
} /**
* 字符串拷贝并转换成大写
*/
static void strcpyToUpper(char *dest, const char *src) {
char in; do {
in = *(src++);
*(dest++) = toupper(in);
} while(in != );
} /**
* 字符串转换成大写
*/
static void strToUpper(char *str) {
char c; do {
c = *(str);
*(str++) = toupper(c);
} while(c != );
} /**
* 字符串转换成小写
*/
static void strToLower(char *str) {
char c; do {
c = *(str);
*(str++) = tolower(c);
} while(c != );
} /* Decode hex string 'str' of length 'len' and return numerical value.
* In case of error in string, set 'err' to 1. */
/**
* 将十六进制的字符串转成数字
*/
static unsigned int hex2dec(const char *str, int len, int *err){
unsigned int val = ;
int i; for(i=; i<len; i++) {
char c = str[i];
if(c >= '' && c <= '') {
c = c - '';
} else if (c >= 'A' && c <= 'F') {
c = c - ('A' - );
}
else {
*err = ;
return ;
}
val = val << | c;
}
return val;
} static void sendCommand(int fd, int sequence, char* command); static void printUsage(void) {
printf(
"Usage: canopen.cgi?wnniiiissdd=xxxx[&rnniiiissdd=]\n"
" - w - One digit - 'W'rite or 'R'ead.\n"
" - nn - Two hex digits of node ID.\n"
" - iiii - Four hex digits of Object Dictionary Index.\n"
" - ss - Two hex digits of Object Dictionary Subindex.\n"
" - dd - One to three digits of data type.\n"
" - xxxx - Value to be written.\n"
"\n"
"Datatypes:\n"
" - b - Boolean.\n"
" - u8, u16, u32, u64 - Unsigned integers.\n"
" - i8, i16, i32, i64 - Signed integers.\n"
" - r32, r64 - Real numbers.\n"
" - t, td - Time of day, time difference.\n"
" - vs - Visible string (between double quotes).\n"
" - os, us, d - Octet string, unicode string, domain."
);
} /******************************************************************************/
int main (int argc, char *argv[], char *env[]) {
char socketPath[] = {}; /* Name of the local domain socket. */ FILE *fp;
int fdSocket;
struct sockaddr_un addr;
char *queryString;
int queryStringAllocated = ; /* whitelist and blacklist are arrays of null separated strings, which
* contains patterns for comparision with commands from query string. */
char *whitelist;
char *blacklist;
int whitelistLen;
int blacklistLen; /* Print mime */
/**
* 输出http协议的头
*/
printf("Content-type:text/plain\n\n"); /* Get program options from configuration file */
/**
* 处理配置文件
*/
fp = fopen("canopen.conf", "r");
if(fp == NULL) {
errExitErrno("Can't open configuration file");
}
else {
const char spaceDelim[] = " \t\n\r\f\v";
char buf[];
int wlSize = ; /* byte length */
int blSize = ;
int wlDataSize = ;
int blDataSize = ; whitelist = (char *) malloc(wlSize);
blacklist = (char *) malloc(blSize);;
// 最开始wlDataSize长度都是0,随着allow检测到的配置越来越多,长度会越来越长
whitelistLen = ; /* number of tokens in list */
blacklistLen = ;
if(whitelist == NULL || blacklist == NULL) {
errExitErrno("Whitelist or Blacklist can't be allocated.");
} // 每次读取一行
while(fgets(buf, sizeof(buf), fp) != NULL) {
char *token;
token = strtok(buf, spaceDelim); if(token == NULL) { }
/**
* 获取socketPath配置
*/
else if(strcasecmp(token, "socketPath") == ) {
if(strlen(socketPath) != ) {
errExit("Duplicate 'socketPath' in canopen.conf.");
}
strncpy(socketPath, strtok(NULL, spaceDelim), sizeof(socketPath));
socketPath[sizeof(socketPath)-] = ;
}
else if(strcasecmp(token, "allow") == ) {
// 保存上一次的wlDataSize长度,随着allow检测到的配置越来越多,长度会越来越长
int prevDataSize = wlDataSize; // 获取value
token = strtok(NULL, spaceDelim);
// 计算value长度并+1,最后一个字节用于存放字符串结束符,这个长度叠加到wlDataSize中
wlDataSize += (strlen(token) + );
// 长度大于预设字符串长度,双倍扩容并重新分配,不过从这里开看最大也就是双倍的扩容长度
while(wlDataSize > wlSize) {
wlSize *= ;
whitelist = (char *) realloc(whitelist, wlSize);
if(whitelist == NULL) {
errExitErrno("Whitelist can't be allocated.");
}
}
// 拷贝当前的匹配数据到whitelist中
strcpyToUpper(&whitelist[prevDataSize], token);
whitelistLen ++;
}
/**
* 类是于白名单
*/
else if(strcasecmp(token, "deny") == ) {
int prevDataSize = blDataSize; token = strtok(NULL, spaceDelim);
blDataSize += (strlen(token) + );
while(blDataSize > blSize) {
blSize *= ;
blacklist = (char *) realloc(blacklist, blSize);
if(blacklist == NULL) {
errExitErrno("Blacklist can't be allocated.");
}
}
strcpyToUpper(&blacklist[prevDataSize], token);
blacklistLen ++;
}
}
} fclose(fp); /* Create and connect client socket */
/**
* 创建本地socket
*/
fdSocket = socket(AF_UNIX, SOCK_STREAM, );
if(fdSocket == -) {
errExitErrno("Socket creation failed");
} /**
* 配置本地socket
*/
memset(&addr, , sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socketPath, sizeof(addr.sun_path) - ); /**
* 连接本地socket
*/
if(connect(fdSocket, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -) {
errExitErrno("Socket connection failed");
} /* get query string */
/**
* 获取网络请求数据
*/
queryString = getenv("QUERY_STRING"); /* HTTP GET method. */
if(queryString != NULL && strlen(queryString) == ) {
queryString = malloc(BUF_SIZE);
if(queryString == NULL) {
errExitErrno("queryString can't be allocated.");
}
queryStringAllocated = ;
fgets(queryString, BUF_SIZE, stdin); /* HTTP POST method. */
}
if(queryString == NULL && argc >= ) {
queryString = argv[]; /* If no query string, try first argument. */
} /* get commands from query string */
/**
* 解析网络请求数据
*/
if(queryString != NULL && strlen(queryString) > ) {
char *command;
int sequence = ; /* put whole query string to upper case */
/**
* 将请求数据转为大写的格式
*/
strToUpper(queryString); command = strtok(queryString, "&");
while(command != NULL) {
int i;
int offset;
int passed = ; /* Test whitelist and blacklist */
/**
* 一个一个偏移着找
*/
offset = ;
for(i=; i<whitelistLen; i++) {
char *patern = &whitelist[offset];
if(fnmatch(patern, command, ) == ) {
passed = ;
break;
}
offset += strlen(patern) + ;
}
/**
* 检查黑名单
*/
if(passed == ) {
offset = ;
for(i=; i<blacklistLen; i++) {
char *patern = &blacklist[offset];
if(fnmatch(patern, command, ) == ) {
passed = -; /* not allowed */
break;
}
offset += strlen(patern) + ;
}
} /* Send command or error message */
if(strlen(command) < ) {
printf("? %s [%d] ERROR: 101 - Syntax error in command.\n", command, sequence);
}
else if(passed == ) {
sendCommand(fdSocket, sequence, command);
}
else {
printf("%c %c%c%c%c%c%c%c%c [%d] ERROR: 100 - Access restriction, command %s.\n",
command[], command[], command[], command[], command[],
command[], command[], command[], command[],
sequence, (passed==)?"not on whitelist":" on blacklist");
} command = strtok(NULL, "&");
sequence ++;
}
}
else {
printUsage();
} close(fdSocket);
free(whitelist); // 释放白名单
free(blacklist); // 释放黑名单
if(queryStringAllocated == ) {
free(queryString);
} exit(EXIT_SUCCESS);
} static void sendCommand(int fd, int sequence, char* command) {
int i, err;
char comm;
unsigned int nodeId, idx, sidx;
char dataType[];
char *value = ""; char buf[BUF_SIZE]; /* Parse command. It is at least 8 characters long. */
/**
* 解析命令
*/
err = ; comm = command[];
if(comm != 'R' && comm != 'W') {
err = ;
} nodeId = hex2dec(&command[], , &err);
if(nodeId < || nodeId > ) {
err = ;
} idx = hex2dec(&command[], , &err);
sidx = hex2dec(&command[], , &err); for(i=; i<sizeof(dataType); i++) {
char c = command[+i]; if(c == '=' || c == ) {
dataType[i] = ;
if(c == '=') {
value = &command[+i];
}
break;
}
dataType[i] = c;
}
if(i > ) {
err = ;
dataType[] = ;
}
if(strlen(value) > (sizeof(buf) - )) {
err = ;
} /* Write command according to CiA309-3. */
/**
* 命令转换,转换成canopend能接收的命令格式
*/
if(err == ) {
size_t wlen, rlen; strToLower(dataType); wlen = sprintf(buf, "[%d] 0x%02X %c 0x%04X 0x%02X %s %s\n",
sequence, nodeId, tolower(comm), idx, sidx, dataType, value); if (write(fd, buf, wlen) != wlen) {
errExit("Socket write failed");
} rlen = read(fd, buf, sizeof(buf)); if(rlen == -) {
errExit("Socket read failed");
} printf("%c %02X%04X%02X %s",
comm, nodeId, idx, sidx, buf);
}
else {
printf("? %s [%d] ERROR: 101 - Syntax error in command.\n",
command, sequence);
}
}

CANopenSocket CANopenCGI.c hacking的更多相关文章

  1. CANopenSocket CANopenCommand.c hacking

    /***************************************************************************** * CANopenSocket CANop ...

  2. ★Kali信息收集~ 1.Google Hacking + Github Hacking

    一.google hacking site site:cnblogs.com 毒逆天 intitle intitle:login allintitle allintitle:index of alli ...

  3. 狗汪汪玩转无线电 -- GPS Hacking

    狗汪汪玩转无线电 -- GPS Hacking Kevin2600 · 2015/12/09 10:12 0x00 序 GPS Hacking 在过去几年的安全会议上一直都是很受关注的议题. 但往往因 ...

  4. GnuRadio Hacking②:使用SDR嗅探北欧芯片无线键盘鼠标数据包

    0×00 前言 上半年的时候安全公司Bastille Networks(巴士底狱)安全研究员发现大多数无线鼠标和接收器之间的通信信号是不加密的,黑客可对一两百米范围内存在漏洞的无线键鼠进行嗅探甚至劫持 ...

  5. GnuRadio Hacking①:使用GnuRadio+SDR破解固定码无线遥控

    0×01 信号捕获 在这篇文章中,我们将使用GnuRadio+SDR硬件对某品牌型号的无线跳蛋进行无线重放攻击的演示. 市面上常见的无线遥控工作的频段,通常工作在315Mhz.433Mhz,也有少数的 ...

  6. GSM Hacking Part② :使用SDR捕获GSM网络数据并解密

    0×00 在文章第一部分 GSM Hacking Part① :使用SDR扫描嗅探GSM网络 搭建了嗅探GSM流量的环境,在第二部中,我们来讨论如何捕获发短信以及通话过程中的流量,从捕获到的数据中解密 ...

  7. 移动安全初探:窃取微信聊天记录、Hacking Android with Metasploit

    在这篇文章中我们将讨论如何获取安卓.苹果设备中的微信聊天记录,并演示如何利用后门通过Metasploit对安卓设备进行控制.文章比较基础.可动手性强,有设备的童鞋不妨边阅读文章边操作,希望能激发大家对 ...

  8. Redis代码阅读之Hacking Strings

    Hacking Strings The implementation of Redis strings is contained in sds.c ( sds stands for Simple Dy ...

  9. RFID Hacking④:使用ProxMark3 破解门禁

    文中提及的部分技术可能带有一定攻击性,仅供安全学习和教学用途,禁止非法使用! 0×00 前言 国际黑客大会Defcon传统之一:开锁!因为黑客认为锁也是一种安全挑战.我们在黑客题材电影.电视剧中也常常 ...

随机推荐

  1. 【HackerRank】 Find Digits

    Find Digits Problem Statement Given a number you have to print how many digits in that number exactl ...

  2. imx6q 添加intel PCIE网卡

    TQ_IMX6Q开发板移植rtl8168-PCIE转千兆网卡 一.配置内核选项PCIE总线驱动支持 默认的内核配置可能没有把PCIE的总线驱动编入内核,所以需要确认是否把驱动编译到了内核里面. 配置好 ...

  3. 20165101刘天野 2017-2018-2 《Java程序设计》第5周学习总结

    #20165101刘天野 2017-2018-2 <Java程序设计>第5周学习总结 教材学习内容总结 第七章:内部类与异常类 内部类(nested classes),面向对象程序设计中, ...

  4. Spark总结1

    安装jdk 下载spark安装包 解压 重点来了: 配置 spark: 进入 conf   ----> spark-env.sh.template文件 cd conf/ mv spark-env ...

  5. R语言笔记004——R批量读取txt文件

    R批量读取txt文件 本文数据,代码都是参考的是大音如霜公众号,只是自己跟着做了一遍. path<-'C:\\Users\\Administrator\\Desktop\\docs' docs& ...

  6. Javascript中的prototype和__proto__的联系区别

    转载至http://www.cnblogs.com/sinstone/p/5136871.html   一.联系 prototype和__proto__都指向原型对象,任意一个函数(包括构造函数)都有 ...

  7. 不小心把服务器上的/usr/lib下的所有文件删除,恢复办法

    手贱,使用root用户,rm -rf 多了一个"*"……导致了万分惊恐的悲剧,/usr/lib下的所有文件被删除…… 修复办法: linux系统是基于文件的,所以只要能拷贝到和原来 ...

  8. android EventBus的简单使用

    今天,简单讲讲Android里关于EventBus的使用. 这几天,由于面试的缘故,我听到了很多Android的流行框架,但是之前自己在公司做APP时并没有使用,所以没有了解.于是在网上查找了资料,学 ...

  9. SSIS的控制流之For循环容器

    SSIS包由一个控制流以及一个或多个数据流(可选)组成.下面的关系图显示具有一个容器和六项任务的控制流. 这些任务中有五项定义于包级别,还有一项定义于容器级别.任务位于容器内.在控制流中的工具箱.我们 ...

  10. 利用selenium爬取豆瓣电影Top250

    这几天在学习selenium,顺便用selenium + python写了一个比较简陋的爬虫,现附上源码,有时间再补充补充: from selenium import webdriver from s ...