ubuntuusers.de

Logouttimer "In 60 Sekunden ausschalten" einfach anpassen per Skript

Status: Gelöst | Ubuntu-Version: 9.10 (Karmic Koala)
Antworten |

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Dass die "60 Sekunden" Verzögerung im Timer-Dialog beim Abschalten von Karmic Koala (und wohl auch Lucid Lynx)
sich nicht einfach anpassen lassen hat ja schon verschiedene Leute geärgert.

Die Lösung für dies Problem war bisher entweder, das betreffende Programm neu zu kompilieren:
http://wiki.ubuntuusers.de/GNOME_Logouttimer_entfernen_oder_anpassen#Timer-anpassen
oder mit dem HEX- Editor die Binärdatei mit Hand zu patchen: http://forum.ubuntuusers.de/topic/moeglichkeit-um-in-60-sekunden-ausschalten-zu/
Beides ist nicht wirklich bequem.

Logouttimer patchen per Skript

Deshalb habe ich für das Patchen der Binärdatei jetzt ein Skript gebaut: timer60patch
Im Wesentlichen macht das Skript nicht viel anderes als beim manuellen Patchen auch,
allerdings wird hier direkt der CPU-Befehl für die Zuweisung der "60" gesucht und angepasst.

Installieren

Das Skript timer60patch einfach hier herunterladen: http://media.ubuntuusers.de/wiki/attachments/19/06/timer60patch
und ausführbar machen. Am einfachsten per Rechtsklick auf die Datei, bei "Eigenschaften" - [Rechte] mit dem Häkchen bei [√] ausführbar.

Ausführen

Das Skript muss auf jeden Fall im Terminal ausgeführt werden, am besten bei Gnome mit (Doppel-) Klick auf die Datei - [im Terminal ausführen].
Das Passwort [Enter] muss man wie immer im Terminal "blind" eintippen, der Rest erklärt sich von selbst:

- Es wird einmalig ein Backup angelegt.
- Die Zeit wird mit [+] und [-] zwischen 1 und 999 Sekunden eingestellt und mit [Enter] übernommen.
- Nachkontrolle der gepatchten Datei - danach schließen mit irgend einer Taste. Fertig.

Funktion

Zuerst fragt das Skript natürlich ab, ob es die Datei /usr/lib/indicator-session/gtk-logout-helper überhaupt existiert.
(sonst ist das womöglich gar kein Karmic oder Lucid ...)
Dann sichert es die Originaldatei (incl. Rechte und Zeitstempel) als /usr/lib/indicator-session/gtk-logout-helper0 .

Danach kann man die vorgeschlagene Zeit von 10 Sekunden mit [+] und [-] ändern und mit [Enter] übernehmen.

Diese Zahl wird byteweise zerlegt (schließlich arbeitet der PC mit der "Little Endian"-Bytefolge,
also 1-er zuerst, dann 256-er, 65536-er, usw., siehe http://de.wikipedia.org/wiki/Byte-Reihenfolge )
und hexadezimal für den Patch formatiert.

Dann erfolgt das Patchen der binären Datei.
Dazu wird die Orignaldatei mit xxd in Hexadezimaldarstellung umgewandelt, die störenden Zeilenumbrüche mit tr entfernt,
das gesuchte Muster mit sed ersetzt und schließlich alles wieder mit xxd in die neue Binärdatei zurückgewandelt.
(siehe dazu auch http://forum.ubuntuusers.de/topic/ersetzen-von-codemustern-in-einer-binaerdatei/ )

Zum Abschluss wird durch einen Binärvergleich mit der gesicherten Originaldatei überprüft was verändert wurde.
Das Ergebnis sollte in etwa so aussehen:

11603  74  12

Wenn hier etwas ganz anderes erscheinen würde, oder größere Unterschiede, würde man das sofort merken.
Dies ist eine sehr effektive Kontrolle ob das Skript einwandfrei funktioniert hat.

Das Skript schließt erst nach einem Tastendruck,
damit man die Ausgabe und eventuelle Fehlermeldungen auf jeden Fall lesen kann.

CPU-Befehle

Das Suchmuster für sed ergibt sich aus dem, was der Compiler an Binärcode aus dem Quelltext

logout_dialog->timeout = 60;

erzeugt. Dies ist ja die direkte Zuweisung einer Konstanten an eine 32 Bit Integer-Variable (die auf dem Stack liegt).
Der Compiler setzt dies üblicherweise um in einen MOV-Befehl mit relativem Offset, bezogen auf das Register EBX, ESI oder EDI,
der die Zahl "60" (= hex "3C") direkt lädt.

Tatsächlich erscheint hier in der Binärdatei dieses Bytemuster (32-Bit Karmic):

Ungültiges Makro

Dieses Makro ist nicht verfügbar

C7 83 CC 00 00 00 3C 00 00 00 = mov DS:[ebx+000000CC],0000003C

( Bei 64-Bit Karmic, wie erwartet mit einem anderen Offset, und sogar auf ein anderes Register bezogen. Dort erscheint:
C7 87 60 01 00 00 3C 00 00 00 = mov DS:[edi+00000160],0000003C )

Allgemein also: C7 8y xx xx xx xx 3C 00 00 00
mit y = Registerkennung (3,6 oder 7) und xxxxxxxx = Offset

(→ zum ausprobieren: online-Disassembler: http://pvdasm.reverse-engineering.net/PVPHP.php )

Dies ist dann also das Suchmuster für sed .

Hier das komplette Skript:

#! /bin/bash

# timer60patch
# patcht ab Ubuntu 9.10 den fest codierten Logoutzähler von 60 Sekunden auf einen einstellbaren Wert im Binärfile.
# Autor: [track]


sec=10
name=timer60patch
fpath=/usr/lib/indicator-session/
fname=gtk-logout-helper


# Datei vohanden ?
if [ -f "$fpath$fname" ]; then
	echo ">$name:	== Das Skript kann jederzeit mit [Strg]-C abgebrochen werden. =="
else
	echo ">$name:	Wo ist die Datei  $fname ?"
	echo ">		Dieses Skript funktioniert erst ab Ubuntu 9.10 (Karmic).	[Taste]"
	read -sn1
	exit 1
fi


# Kopie schon vohanden ?
if [ -f "$fpath$fname"0 ]; then
	echo
	echo "Kopie ist vorhanden: $fpath$fname""0"
	echo
else
	echo " ( Kopie sichern, das Passwort bitte )"
	sudo cp -p $fpath$fname $fpath$fname""0
	if [ $? -gt 0 ]; then
		echo "Abbruch, kopieren nicht möglich.		[Taste]"
		read -sn1
		exit 2
	fi
	echo "Kopie wurde gesichert: $fpath$fname""0"
	echo
fi


# Zeit einstellen:
kb=0
until [ "$kb" == "" ]; do
	echo -en "\rCountdown:  [$sec]sec 		bitte einstellen: [+][-]  und bestätigen: [Enter]"
	read -akb -sn1
	if [ "$kb" == "+" ]; then 
		if [ $sec -lt 999 ]; then sec=$(( $sec + 1 )) ; fi
	elif [ "$kb" == "-" ]; then 
		if [ $sec -gt 1 ]; then sec=$(( $sec - 1 )) ; fi
	fi
done
echo

sec1=$(( $sec % 256 ))
sec2=$(( $sec / 256 ))
# echo [ $sec1 / $sec2 ]				# optional: Anzeige der Byte-Zuordnung


# Patchmuster:
	# Der Zahlenwert "60" wird direkt auf einer 32 bit Stack-Variablen abgelegt
	# bei 64-Bit System Uby 9.10:
	# C7 87  60 01 00 00  3C 00 00 00 = mov DS:[edi+00000160],0000003C
	# bei 32-Bit System Uby 9.10:
	# C7 83  CC 00 00 00  3C 00 00 00 = mov DS:[ebx+000000CC],0000003C

	# Es kann aber je nach Compilerlauf auch anders aussehen:
	# 	C7 83 xx xx xx xx 3C 00 00 00 = mov DS:[ebx+xxxxxxxx],0000003C
	# oder:	C7 86 xx xx xx xx 3C 00 00 00 = mov DS:[esi+xxxxxxxx],0000003C
	# oder:	C7 87 xx xx xx xx 3C 00 00 00 = mov DS:[edi+xxxxxxxx],0000003C

p0=c78\\\([367]........\\\)3c00				# allgemeines Suchmuster
p2=$( printf "c78\\\1%2.2x%2.2x" $sec1 $sec2 )		# Zielmuster


# Patch anwenden:
 # (perl -pi -e 's/pattern/replacement/g' file	funktioniert nicht bei binären Ausdrücken)
 # Andere Idee:	http://www.mail-archive.com/peterboro@mailman.lug.org.uk/msg00204.html
 # 		(+ mod.: die Zeilenbegrenzung mit "tr -d \n" beseitigt.)

echo
echo " ( zum patchen das Passwort bitte )"

# echo "sed \"s/$p0/$p2/\""				# optional: Anzeige des sed-Befehls

xxd -p $fpath$fname""0 | tr -d "\n" | sed "s/$p0/$p2/" | sudo xxd -r -p - $fpath$fname
if [ $? -gt 0 ]; then
	echo "Abbruch, patchen geht nicht. Passwort falsch ?		[Taste]"
	read -sn1
	exit 3
else
	echo " .. gepatcht."
	echo
fi

# nochmal binär vergleichen:
cmp -l $fpath$fname""0 $fpath$fname | head

echo "Der Countdown ist jetzt auf $sec Sekunden eingestellt.		[Taste]"
read -sn1
exit 0

track


p.s.: Ergänzungen, Korrekturen, Kommentare willkommen !

Bilder

jug Team-Icon

Ehemalige
Avatar von jug

Anmeldungsdatum:
19. März 2007

Beiträge: 12335

Wohnort: Berlin

Was hat sich verändert? Du hast doch schonmal darüber referiert und wurdest darauf hingewiesen, dass das Forum kein guter Ort für solche Anleitungen ist …

Bitte da weiter machen: http://forum.ubuntuusers.de/topic/moeglichkeit-um-in-60-sekunden-ausschalten-zu/

~jug

Antworten |