Merge branch 'dev' into stm32f4

This commit is contained in:
dataisland
2021-11-26 18:20:17 +08:00
11 changed files with 322 additions and 215 deletions
+26
View File
@@ -0,0 +1,26 @@
all: server arm_server
clean:
@rm -rf *.o
@rm -rf server
@rm -rf arm_server
server: main.o httpd.o
gcc -o server $^
@rm -rf *.o
main.o: main.c httpd.h
gcc -c -o main.o main.c
httpd.o: httpd.c httpd.h
gcc -c -o httpd.o httpd.c
arm_server: arm_main.o arm_httpd.o
arm-linux-gnueabi-gcc-10 -o arm_server $^
@rm -rf *.o
arm_main.o: main.c httpd.h
arm-linux-gnueabi-gcc-10 -c -o arm_main.o main.c
arm_httpd.o: httpd.c httpd.h
arm-linux-gnueabi-gcc-10 -c -o arm_httpd.o httpd.c
+199
View File
@@ -0,0 +1,199 @@
#include "httpd.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <signal.h>
#define CONNMAX 1000
char *method, // "GET" or "POST"
*uri, // "/index.html" things before '?'
*qs, // "a=1&b=2" things after '?'
*prot; // "HTTP/1.1"
char *payload; // for POST
int payload_size;
static int listenfd, clients[CONNMAX];
static void error(char *);
static void startServer(const char *);
static void respond(int);
typedef struct { char *name, *value; } header_t;
static header_t reqhdr[17] = { {"\0", "\0"} };
static int clientfd;
static char *buf;
void serve_forever(const char *PORT)
{
struct sockaddr_in clientaddr;
socklen_t addrlen;
char c;
int slot=0;
printf(
"Server started %shttp://127.0.0.1:%s%s\n",
"\033[92m",PORT,"\033[0m"
);
// Setting all elements to -1: signifies there is no client connected
int i;
for (i=0; i<CONNMAX; i++)
clients[i]=-1;
startServer(PORT);
// Ignore SIGCHLD to avoid zombie threads
signal(SIGCHLD,SIG_IGN);
// ACCEPT connections
while (1)
{
addrlen = sizeof(clientaddr);
clients[slot] = accept (listenfd, (struct sockaddr *) &clientaddr, &addrlen);
if (clients[slot]<0)
{
perror("accept() error");
}
else
{
if ( fork()==0 )
{
respond(slot);
exit(0);
}
}
while (clients[slot]!=-1) slot = (slot+1)%CONNMAX;
}
}
//start server
void startServer(const char *port)
{
struct addrinfo hints, *res, *p;
// getaddrinfo for host
memset (&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if (getaddrinfo( NULL, port, &hints, &res) != 0)
{
perror ("getaddrinfo() error");
exit(1);
}
// socket and bind
for (p = res; p!=NULL; p=p->ai_next)
{
int option = 1;
listenfd = socket (p->ai_family, p->ai_socktype, 0);
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
if (listenfd == -1) continue;
if (bind(listenfd, p->ai_addr, p->ai_addrlen) == 0) break;
}
if (p==NULL)
{
perror ("socket() or bind()");
exit(1);
}
freeaddrinfo(res);
// listen for incoming connections
if ( listen (listenfd, 1000000) != 0 )
{
perror("listen() error");
exit(1);
}
}
// get request header
char *request_header(const char* name)
{
header_t *h = reqhdr;
while(h->name) {
if (strcmp(h->name, name) == 0) return h->value;
h++;
}
return NULL;
}
//client connection
void respond(int n)
{
int rcvd, fd, bytes_read;
char *ptr;
buf = malloc(65535);
rcvd=recv(clients[n], buf, 65535, 0);
if (rcvd<0) // receive error
fprintf(stderr,("recv() error\n"));
else if (rcvd==0) // receive socket closed
fprintf(stderr,"Client disconnected upexpectedly.\n");
else // message received
{
buf[rcvd] = '\0';
method = strtok(buf, " \t\r\n");
uri = strtok(NULL, " \t");
prot = strtok(NULL, " \t\r\n");
fprintf(stderr, "\x1b[32m + [%s] %s\x1b[0m\n", method, uri);
if (qs = strchr(uri, '?'))
{
*qs++ = '\0'; //split URI
} else {
qs = uri - 1; //use an empty string
}
header_t *h = reqhdr;
char *t, *t2;
while(h < reqhdr+16) {
char *k,*v,*t;
k = strtok(NULL, "\r\n: \t"); if (!k) break;
v = strtok(NULL, "\r\n"); while(*v && *v==' ') v++;
h->name = k;
h->value = v;
h++;
fprintf(stderr, "[H] %s: %s\n", k, v);
t = v + 1 + strlen(v);
if (t[1] == '\r' && t[2] == '\n') break;
}
t++; // now the *t shall be the beginning of user payload
t2 = request_header("Content-Length"); // and the related header if there is
payload = t;
payload_size = t2 ? atol(t2) : (rcvd-(t-buf));
// bind clientfd to stdout, making it easier to write
clientfd = clients[n];
dup2(clientfd, STDOUT_FILENO);
close(clientfd);
// call router
route();
// tidy up
fflush(stdout);
shutdown(STDOUT_FILENO, SHUT_WR);
close(STDOUT_FILENO);
}
//Closing SOCKET
shutdown(clientfd, SHUT_RDWR); //All further send and recieve operations are DISABLED...
close(clientfd);
clients[n]=-1;
}
+37
View File
@@ -0,0 +1,37 @@
#ifndef _HTTPD_H___
#define _HTTPD_H___
#include <string.h>
#include <stdio.h>
//Server control functions
void serve_forever(const char *PORT);
// Client request
extern char *method, // "GET" or "POST"
*uri, // "/index.html" things before '?'
*qs, // "a=1&b=2" things after '?'
*prot; // "HTTP/1.1"
extern char *payload; // for POST
extern int payload_size;
char *request_header(const char* name);
// user shall implement this function
void route();
// some interesting macro for `route()`
#define ROUTE_START() if (0) {
#define ROUTE(METHOD,URI) } else if (strcmp(URI,uri)==0&&strcmp(METHOD,method)==0) {
#define ROUTE_GET(URI) ROUTE("GET", URI)
#define ROUTE_POST(URI) ROUTE("POST", URI)
#define ROUTE_END() } else printf(\
"HTTP/1.1 500 Not Handled\r\n\r\n" \
"The server has no handler to the request.\r\n" \
);
#endif
+27
View File
@@ -0,0 +1,27 @@
#include "httpd.h"
int main(int c, char** v, int argc, const char **argv)
{
serve_forever("12913");
return 0;
}
void route()
{
ROUTE_START()
ROUTE_GET("/")
{
printf("HTTP/1.1 200 OK\r\n\r\n");
printf("httpd_test_successful");
}
ROUTE_POST("/")
{
printf("HTTP/1.1 200 OK\r\n\r\n");
printf("Wow, seems that you POSTed %d bytes. \r\n", payload_size);
printf("Fetch the data using `payload` variable.");
}
ROUTE_END()
}
+1
View File
@@ -0,0 +1 @@
copy from: https://gist.github.com/laobubu/d6d0e9beb934b60b2e552c2d03e1409e
-187
View File
@@ -1,187 +0,0 @@
/*
AUTHOR: Abhijeet Rastogi (http://www.google.com/profiles/abhijeet.1989)
This is a very simple HTTP server. Default port is 10000 and ROOT for the server is your current working directory..
You can provide command line arguments like:- $./a.aout -p [port] -r [path]
for ex.
$./a.out -p 50000 -r /home/
to start a server at port 50000 with root directory as "/home"
$./a.out -r /home/shadyabhi
starts the server at port 10000 with ROOT as /home/shadyabhi
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<signal.h>
#include<fcntl.h>
#define CONNMAX 1000
#define BYTES 1024
char *ROOT;
int listenfd, clients[CONNMAX];
void error(char *);
void startServer(char *);
void respond(int);
int main(int argc, char* argv[])
{
struct sockaddr_in clientaddr;
socklen_t addrlen;
char c;
//Default Values PATH = ~/ and PORT=10000
char PORT[6];
ROOT = getenv("PWD");
strcpy(PORT,"10000");
int slot=0;
//Parsing the command line arguments
while ((c = getopt (argc, argv, "p:r:")) != -1)
switch (c)
{
case 'r':
ROOT = malloc(strlen(optarg));
strcpy(ROOT,optarg);
break;
case 'p':
strcpy(PORT,optarg);
break;
case '?':
fprintf(stderr,"Wrong arguments given!!!\n");
exit(1);
default:
exit(1);
}
printf("Server started at port no. %s%s%s with root directory as %s%s%s\n","\033[92m",PORT,"\033[0m","\033[92m",ROOT,"\033[0m");
// Setting all elements to -1: signifies there is no client connected
int i;
for (i=0; i<CONNMAX; i++)
clients[i]=-1;
startServer(PORT);
// ACCEPT connections
while (1)
{
addrlen = sizeof(clientaddr);
clients[slot] = accept (listenfd, (struct sockaddr *) &clientaddr, &addrlen);
if (clients[slot]<0)
error ("accept() error");
else
{
if ( fork()==0 )
{
respond(slot);
exit(0);
}
}
while (clients[slot]!=-1) slot = (slot+1)%CONNMAX;
}
return 0;
}
//start server
void startServer(char *port)
{
struct addrinfo hints, *res, *p;
// getaddrinfo for host
memset (&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if (getaddrinfo( NULL, port, &hints, &res) != 0)
{
perror ("getaddrinfo() error");
exit(1);
}
// socket and bind
for (p = res; p!=NULL; p=p->ai_next)
{
listenfd = socket (p->ai_family, p->ai_socktype, 0);
if (listenfd == -1) continue;
if (bind(listenfd, p->ai_addr, p->ai_addrlen) == 0) break;
}
if (p==NULL)
{
perror ("socket() or bind()");
exit(1);
}
freeaddrinfo(res);
// listen for incoming connections
if ( listen (listenfd, 1000000) != 0 )
{
perror("listen() error");
exit(1);
}
}
//client connection
void respond(int n)
{
char mesg[99999], *reqline[3], data_to_send[BYTES], path[99999];
int rcvd, fd, bytes_read;
memset( (void*)mesg, (int)'\0', 99999 );
rcvd=recv(clients[n], mesg, 99999, 0);
if (rcvd<0) // receive error
fprintf(stderr,("recv() error\n"));
else if (rcvd==0) // receive socket closed
fprintf(stderr,"Client disconnected upexpectedly.\n");
else // message received
{
printf("%s", mesg);
reqline[0] = strtok (mesg, " \t\n");
if ( strncmp(reqline[0], "GET\0", 4)==0 )
{
reqline[1] = strtok (NULL, " \t");
reqline[2] = strtok (NULL, " \t\n");
if ( strncmp( reqline[2], "HTTP/1.0", 8)!=0 && strncmp( reqline[2], "HTTP/1.1", 8)!=0 )
{
write(clients[n], "HTTP/1.0 400 Bad Request\n", 25);
}
else
{
if ( strncmp(reqline[1], "/\0", 2)==0 )
reqline[1] = "/index.html"; //Because if no file is specified, index.html will be opened by default (like it happens in APACHE...
strcpy(path, ROOT);
strcpy(&path[strlen(ROOT)], reqline[1]);
printf("file: %s\n", path);
if ( (fd=open(path, O_RDONLY))!=-1 ) //FILE FOUND
{
send(clients[n], "HTTP/1.0 200 OK\n\n", 17, 0);
while ( (bytes_read=read(fd, data_to_send, BYTES))>0 )
write (clients[n], data_to_send, bytes_read);
}
else write(clients[n], "HTTP/1.0 404 Not Found\n", 23); //FILE NOT FOUND
}
}
}
//Closing SOCKET
shutdown (clients[n], SHUT_RDWR); //All further send and recieve operations are DISABLED...
close(clients[n]);
clients[n]=-1;
}
+1 -1
View File
@@ -223,4 +223,4 @@ def ql_syscall_rename(ql: Qiling, oldname_buf: int, newname_buf: int):
ql.log.exception(f"rename(): {newpath} exists!")
regreturn = -1
return regreturn
return regreturn
+3 -2
View File
@@ -278,13 +278,14 @@ def ql_syscall_setsockopt(ql: Qiling, sockfd, level, optname, optval_addr, optle
def ql_syscall_shutdown(ql: Qiling, shutdown_fd, shutdown_how):
regreturn = 0
if 0 <= shutdown_fd < NR_OPEN and ql.os.fd[shutdown_fd] != 0:
try:
ql.os.fd[shutdown_fd].shutdown(shutdown_how)
except:
regreturn = -1
else:
regreturn = 0
return regreturn
+28 -15
View File
@@ -3,7 +3,7 @@
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import platform, sys, unittest, subprocess, string, random, os
import platform, sys, unittest, os, threading, time
from unicorn import UcError, UC_ERR_READ_UNMAPPED, UC_ERR_FETCH_UNMAPPED
@@ -281,27 +281,40 @@ class ELFTest(unittest.TestCase):
self.assertEqual("server sendto() 14 return 14.\n", ql.buf_out)
del ql
def test_http_elf_linux_x8664(self):
def picohttpd():
ql = Qiling(["../examples/rootfs/x8664_linux/bin/picohttpd"], "../examples/rootfs/x8664_linux", multithread=True, verbose=QL_VERBOSE.DEBUG)
ql.run()
def test_udp_elf_linux_arm(self):
def check_write(ql, write_fd, write_buf, write_count, *args, **kw):
try:
buf = ql.mem.read(write_buf, write_count)
buf = buf.decode()
if buf.startswith("server sendto()"):
ql.buf_out = buf
except:
pass
picohttpd_therad = threading.Thread(target=picohttpd, daemon=True)
picohttpd_therad.start()
ql = Qiling(["../examples/rootfs/arm_linux/bin/arm_udp_test","20010"], "../examples/rootfs/arm_linux", multithread=True)
ql.set_syscall("write", check_write, QL_INTERCEPT.ENTER)
ql.run()
time.sleep(1)
self.assertEqual("server sendto() 14 return 14.\n", ql.buf_out)
f = os.popen("curl http://127.0.0.1:12913")
self.assertEqual("httpd_test_successful", f.read())
def test_http_elf_linux_arm(self):
def picohttpd():
ql = Qiling(["../examples/rootfs/arm_linux/bin/picohttpd"], "../examples/rootfs/arm_linux", multithread=True, verbose=QL_VERBOSE.DEBUG)
ql.run()
picohttpd_therad = threading.Thread(target=picohttpd, daemon=True)
picohttpd_therad.start()
time.sleep(1)
f = os.popen("curl http://127.0.0.1:12913")
self.assertEqual("httpd_test_successful", f.read())
del ql
if __name__ == "__main__":
unittest.main()
-1
View File
@@ -1 +0,0 @@
test_done
-9
View File
@@ -1,9 +0,0 @@
<!doctype html>
<html>
<head>
<title>This is the title of the webpage!</title>
</head>
<body>
<a href="flag.txt">click</a>
</body>
</html>