mirror of
https://github.com/qilingframework/qiling.git
synced 2026-10-12 02:21:40 +00:00
Merge branch 'dev' into stm32f4
This commit is contained in:
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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()
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
copy from: https://gist.github.com/laobubu/d6d0e9beb934b60b2e552c2d03e1409e
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 +0,0 @@
|
||||
test_done
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user