Python

Estrarre un’immagine multi-file u-boot in Python

Questo semplice pezzo di codice mostra come estrarre/decomprimere un’immagine u-boot multi-file creata con il comando mkimage, utilizzando Python. Il formato dell’immagine del file u-boot è abbastanza semplice:

64 byte per l'image header.
4 byte per la dimensione della prima immagine.
4 byte per la dimensione della seconda immagine.
...
4 byte a zero per la terminazione.
immagine1.
immagine2.
...

Dovete anche ricordarvi che ogni immagine deve essere paddata a 4 byte.

#!/usr/bin/env python

import sys

def toNumber(buf):
        """ Convert string in number """
        size = 0
        for b in buf: size=size*256+ord(b)
        return size

if len(sys.argv)!=2:
        sys.stdout.write('Usage %s uboot_image_file\n' % sys.argv[0])
        sys.exit(1)

f = open(sys.argv[1],'rb')
f.seek(64) # skip image header

parts = []

# get file size of all images
while True:
        buf = f.read(4)
        size = toNumber(buf)
        if size==0: break
        parts.append(size)

i = 0
for size in parts:
        pattern = 'file%d.img' % i
        p = open(pattern, 'wb')
        buf = f.read(size)
        p.write(buf)
        p.close()
        if size%4 != 0:
                # 4 byte padding
                f.read(4-(size%4))
        i+=1

f.close()

Esempio di Segnali e Slot con QThread su PySide

In questi giorni ho iniziato a studiare PySide. Dopo alcuni giorni spesi a leggere un bel po’ di materiale online, ho pensato che un esempio reale potesse essere utile per chi come come me intende cimentarsi con PySide. In questo esempio vi vieme mostrato come potete implementare un segnale custom (MySignal) insieme all’uso dei thread con QThread.

Il codice seguente crea una finestra con due pulsanti: il primo avvia e ferma un thread (MyThread) che lancia un processo il quale stampa sullo standard output della console un punto ogni secondo continuamente. Il secondo bottone vi permette solo di avviare un altro thread (MyLongThread) che stampa un asterisco sullo standard output ogni secondo per 10 secondi e poi esce.

Questo esempio utilizza la versione delle API 2 (introdotta con PyQt 4.5) per connettere i segnali agli slot.

#!/usr/bin/env python2

import sys, time
from PySide.QtGui import *
from PySide.QtCore import *

class MySignal(QObject):
	sig = Signal(str)

class MyLongThread(QThread):
	def __init__(self, parent = None):
		QThread.__init__(self, parent)
		self.exiting = False
		self.signal = MySignal()

	def run(self):
		end = time.time()+10
		while self.exiting==False:
			sys.stdout.write('*')
			sys.stdout.flush()
			time.sleep(1)
			now = time.time()
			if now>=end:
				self.exiting=True
		self.signal.sig.emit('OK')

class MyThread(QThread):
	def __init__(self, parent = None):
		QThread.__init__(self, parent)
		self.exiting = False

	def run(self):
		while self.exiting==False:
			sys.stdout.write('.')
			sys.stdout.flush()
			time.sleep(1)

class MainWindow(QMainWindow):
	def __init__(self, parent=None):
		QMainWindow.__init__(self,parent)
		self.centralwidget = QWidget(self)
		self.batchbutton = QPushButton('Start batch',self)
		self.longbutton = QPushButton('Start long (10 seconds) operation',self)
		self.label1 = QLabel('Continuos batch')
		self.label2 = QLabel('Long batch')
		self.vbox = QVBoxLayout()
		self.vbox.addWidget(self.batchbutton)
		self.vbox.addWidget(self.longbutton)
		self.vbox.addWidget(self.label1)
		self.vbox.addWidget(self.label2)
		self.setCentralWidget(self.centralwidget)
		self.centralwidget.setLayout(self.vbox)
		self.thread = MyThread()
		self.longthread = MyLongThread()
		self.batchbutton.clicked.connect(self.handletoggle)
		self.longbutton.clicked.connect(self.longoperation)
		self.thread.started.connect(self.started)
		self.thread.finished.connect(self.finished)
		self.thread.terminated.connect(self.terminated)
		self.longthread.signal.sig.connect(self.longoperationcomplete)

	def started(self):
		self.label1.setText('Continuous batch started')

	def finished(self):
		self.label1.setText('Continuous batch stopped')

	def terminated(self):
		self.label1.setText('Continuous batch terminated')

	def handletoggle(self):
		if self.thread.isRunning():
			self.thread.exiting=True
			self.batchbutton.setEnabled(False)
			while self.thread.isRunning():
				time.sleep(0.01)
				continue
			self.batchbutton.setText('Start batch')
			self.batchbutton.setEnabled(True)
		else:
			self.thread.exiting=False
			self.thread.start()
			self.batchbutton.setEnabled(False)
			while not self.thread.isRunning():
				time.sleep(0.01)
				continue
			self.batchbutton.setText('Stop batch')
			self.batchbutton.setEnabled(True)

	def longoperation(self):
		if not self.longthread.isRunning():
			self.longthread.exiting=False
			self.longthread.start()
			self.label2.setText('Long operation started')
			self.longbutton.setEnabled(False)

	def longoperationcomplete(self,data):
		self.label2.setText('Long operation completed with: '+data)
		self.longbutton.setEnabled(True)

if __name__=='__main__':
	app = QApplication(sys.argv)
	window = MainWindow()
	window.show()
	sys.exit(app.exec_())

Per ulteriori informazioni potete dare un’occhiata ai seguenti link:
Documentazione sul modulo QThread: http://doc.qt.nokia.com/latest/qthread.html
Segnali e Slot di PySide: http://developer.qt.nokia.com/wiki/Signals_and_Slots_in_PySide
PyQt Api 2 con PySide: http://www.pyside.org/docs/pseps/psep-0101.html

Come eseguire comandi con privilegi di uno specifico utente in C and Python su Linux

Se avete accesso da root ma avete bisogno di eseguire alcuni applicazioni o script con credenziali di altri utenti potete semplicemente farlo direttamente dalla shell con:

su - username -c "command to execute"

Ma se invece avete bisogno di eseguire tale programma dalla vostra applicazione C/C++ avete bisogno di seguire questa procedura:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>

int main(int argc, char* argv[])
{
        if(argc != 3)
        {
                printf("Usage: %s [USERNAME] [COMMAND]\n",argv[0]);
                return 1;
        }
        char *env[16];
        char envc[16][64];
        struct passwd *pw = getpwnam(argv[1]);
        if(pw==NULL)
        {
                printf("User %s does not exists!\n",argv[1]);
                return 1;
        }

        sprintf(env[0]=envc[0],"TERM=xterm");
        sprintf(env[1]=envc[1],"USER=%s",pw->pw_name);
        sprintf(env[2]=envc[2],"HOME=%s",pw->pw_dir);
        sprintf(env[3]=envc[3],"SHELL=%s",pw->pw_shell);
        sprintf(env[4]=envc[4],"LOGNAME=%s",pw->pw_name);
        sprintf(env[5]=envc[5],"PATH=/usr/bin:/bin:/opt/bin");
        env[6]=0;

        initgroups(argv[1],pw->pw_gid);
        setgid(pw->pw_gid);
        setuid(pw->pw_uid);
        execve(argv[2],NULL,env);

        return 0;
}

Potete compilare ed eseguire il codice in questo modo:

[root@barracuda ~]# gcc mysu.c -o mysu
[root@barracuda ~]# id
uid=0(root) gid=0(root) gruppi=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),19(log)
[root@barracuda ~]# ./mysu matteo /bin/bash
[matteo@barracuda /root]$ id
uid=1000(matteo) gid=100(users) groups=100(users),3(sys),10(wheel),14(uucp),91(video),92(audio),93(optical),95(storage),96(scanner),97(camera),98(power),108(vboxusers)

Lo stesso risultato si puo’ ottenere anche in Python con pochissimo sforzo:

#!/usr/bin/env python

import sys,pwd,os

pw = pwd.getpwnam(sys.argv[1])
os.initgroups(sys.argv[1],pw.pw_gid)
env={"TERM":"xterm","USER":pw.pw_name,"HOME":pw.pw_dir,"SHELL":pw.pw_shell,"LOGNAME":pw.pw_name,"PATH":"/usr/bin:/bin:/opt/bin"};
os.setgid(pw.pw_gid);
os.setuid(pw.pw_uid);
os.execve(sys.argv[2],[],env);

Come implementare l’algoritmo MAC_X919 in Python

Oggi insieme al mio amico Nicola stavo cercando in rete l’implementazione dell’algoritmo X9.19 in python. Purtroppo non l’abbiamo trovato da nessuna parte per cui ce lo siamo fatti da soli:

#!/usr/bin/env python2

import Crypto.Cipher.DES as des
import Crypto.Cipher.DES3 as des3

def mac_x919(key,data):
  while len(data) % 8 != 0:
    data += '\x00'
  des_key1 = des.new(key[0:8],des.MODE_CBC)
  des_key2 = des.new(key[0:8],des.MODE_ECB)
  buf = des_key1.encrypt(data)
  buf = buf[len(buf)-8:]
  buf = des_key2.decrypt(buf)
  des3_key = des3.new(key,des3.MODE_ECB)
  buf = des3_key.encrypt(buf)
  return buf[0:4]

mac = mac_x919('0123456789abcdef','test data to be encrypted')