Passwortschutz Excel

loopzone

gesperrt
Registriert
14 Juli 2013
Beiträge
815
Hallo zusammen.

Ich habe viele Exceltabellen vorliegen, deren Blätter schreibgeschützt sind. Ich habe gelesen, wie die Passwörter entfernt werden können. Das klappt soweit auch sehr gut.
Aber wie kann ich das verwendete Passwort herausfinden, ohne es löschen zu müssen? Es sind so viele Dateien, dass es leichter wäre das Passwort einzugeben und es nicht für jedes Blatt zu löschen.

Ich habe hier gelesen, wie ich den Blattschutz durch Verwendung eines Zip-Programms aushebeln kann:
Ist es möglich aus dem dort zu sehenden "password" einen Rückschluss auf das tatsächliche Passwort zu ziehen? Was heißt also "E76A" aus dem Beispiel als konkretes Passwort?

Hier ist zu erlesen wie man den Blattschutz per Makro aufhebt:
Leider verstehe ich nicht, welche Logik hinter dem Makro steckt. Weiß jemand ob ich es auch nutzen kann um das Passwort zu ermitteln?

Vielen Dank

PS: Um hier evtl. Fragen vorzubeugen, kann ich sagen dass die Dateien nicht von mir sind. Ich muss sie lediglich ausfüllen und würde das gerne automatisieren. Leider geht das nur wenn ich bestimmte Bereiche vom Schutz befreie.
 
Das Passwort ist im Allgemeinen nicht rekonstruierbar, weil bloss ein Hashwert in der Excel-Datei gespeichert wird. Möglich ist u.U. eine Kollision zu finden, welche denselben Hash-Wert liefert. In aktuellen Office-Open-XML-Versionen können dazu diverse Hash-Algorithmen, optional mit Salt und mehreren Iterationen, verwendet werden, vgl. ; wenn deine Excel-Dateien dieses Schema (algorithmName, hashValue, ggf. saltValue) verwenden, was wohl seit Office 2013 der Fall ist, besteht kaum eine Chance, in sinnvoller Zeit eine Kollision zu finden - ausserdem wäre sie, sofern die Salts nicht identisch sind und du nicht zufällig das ursprüngliche Passwort errätst u.U. sogar nur für eine einzelne Datei gültig. In diesem Fall ist auch das erwähnte Makro nutzlos, allerdings ist es natürlich möglich, mit einem simplen Skript die OOXML-Datei zu entpacken, die Zeile, welche das sheetProtection-Element enthält zu entfernen, und sie dann wieder zu packen. In einer unixoiden Shell reichen dazu unzip/grep -v/zip.

Wird der alte Hash-Algorithmus verwendet (password-Attribut im sheetProtection-Element), dann kannst du trivial eine Kollision finden - dies tut auch das von dir erwähnte Makro. Unter ist eine Version zu finden, welche die gefundene Kollision nicht nur nutzt, um das Sheet zu entsperren, sondern auch ausgibt. Sofern dasselbe Passwort verwendet wurde, ist sie meines Wissens auch auf andere Excel-Sheets übertragbar.
 
Oder du lässt passende Software eine Brute-Force-Attacke durchführen, wenn du die Berechnungen auf die GPU auslagerst kann das sogar was werden:
 
Für den modernen Passwortschutz (ab Office 2013) mit sinnvollem Hash-Algorithmus und Salt würde sich eher oclHashcat anbieten, da wesentlich effizienter und flexibler (und ausserdem frei verfügbar). Für den alten Hash-Algorithmus (password-Attribut) ist das ohnehin nicht nötig, da man selbst mit einem VBA-Skript innerhalb weniger Minuten eine Kollision finden kann.
 
ich bin jetzt einfach mal von 2013 ausgegangen, alles davor ist ja wirklich nur ne minutensache auch per CPU... Ich hab das elcomsoft-ding auch nur rausgesucht weil man da gleich direkt die xlsx-datei reinwerfen kann und los gehts, man braucht kein hintergrundwissen über gesalzene oder ungesalzene hashes oder ähnliches. ich bevorzuge allerdings die klassische combi aus hashcat-suite und john the ripper ^^ Damit hat der Penetration-Test auf unserem firmeneigenen AD richtig Spass gemacht

Wenn loopzone das ganze also nur als einmalige aktion ansieht, kann er ja mal den programmnamen bei einschlägigen seiten eingeben, da wird man fündig. Idealerweise nimmt man aber doch oclhashcat und lernt nebenbei noch was :)
 
  • Thread Starter Thread Starter
  • #6
Hallo Leute.

Danke für euren Input. AdvancedPasswordRecovery kenne ich. Hat bei mir aber nie funktioniert.

Das Makro hat allerdings perfekt funktioniert. Es ermittelt ein Passwort, das mit Sicherheit nicht das vergebene ist, aber dennoch funktioniert. Verrückt!
Kugelfisch, kannst du mir erklären, was genau das Makro tut? Ich verstehe es nicht. D.h., ich würde gerne verstehen warum die ersten Variablen nur A und B ergeben und die letzte das komplette Spektrum abdeckt.

Grüße

PS: Entschuldigung für meine späte Rückmeldung
 
Kugelfisch, kannst du mir erklären, was genau das Makro tut? Ich verstehe es nicht. D.h., ich würde gerne verstehen warum die ersten Variablen nur A und B ergeben und die letzte das komplette Spektrum abdeckt.
Der Grund dafür ist, dass die verwendete Hash-Funktion extrem schwach ist, und der Hash-Wert mit 16 Bit Länge zudem so kurz ist, dass Kollisionen schlicht unvermeidlich sind (siehe auch ). Eine Beispielimplementierung der Hash-Funktion findet sich in der Spezifikation von Office Open XML (ECMA-376, Part 4):
[src=c]// Function Input:
// szPassword: NULL terminated C-Style string
// cchPassword: The number of characters in szPassword (not including the NULL terminator)
unsigned_short GetPasswordHash(const char *szPassword, int cchPassword) {
unsigned_short wPasswordHash;
const char *pch;
wPasswordHash = 0;
if (cchPassword > 0) {
pch = &szPassword[cchPassword];
while (pch-- != szPassword) {
wPasswordHash = ((wPasswordHash >> 14) & 0x01) | ((wPasswordHash << 1) & 0x7fff);
wPasswordHash ^= *pch;
}
wPasswordHash = ((wPasswordHash >> 14) & 0x01) | ((wPasswordHash << 1) & 0x7fff);
wPasswordHash ^= cchPassword;
wPasswordHash ^= (0x8000 | ('N' << 8) | 'K');
}
return(wPasswordHash);
}[/src]
Prinzipiell besteht der Hash-Algorithmus darin, für jedes Zeichen des Passworts, angefangen beim letzten(!), die unteren 15 Bits des aktuellen Hash-Werts nach links zu rotieren, und dann die unteren 8 Bits mit dem Passwort-Zeichen über eine XOR-Operation zu verknüpfen. Am Ende wird auf dieselbe Weise noch die Passwort-Länge hinzugefügt und das Ergebnis mit der Konstanten (0x8000 | ('N' << 8) | 'K') = 0xCE4B XOR-verknüpft. Durch die Konstruktion des Passworts aus `A` und `B`, die sich bloss durch das niederwertigste Bit unterscheiden, kann man gezielt bestimmte Bits im erzeugten Hash-Wert ändern - es lässt sich leicht zeigen, dass man dadurch den gesamten Wertebereich (der übrigens real nicht einmal 16 Bit, sondern bloss 15 Bit umfasst, da die einzige Operation, welche das höchstwertige Bit beeinflusst, die abschliessende XOR-Verknüpfung mit 0x8000|... ist - dadurch ist das Bit immer gesetzt) der Hash-Funktion abdecken kann.

Das folgende C-Programm verwendet denselben Algorithmus zur Konstruktion von Kollisionen wie dein VBA-Skript, und testet dabei, ob alle denkbaren Hash-Werte dabei getroffen werden, indem dann hashvalues[hash] gesetzt wird:
[src=c]#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {

char *hashvalues = malloc(0x7FFF);
memset(hashvalues, 0, 0x7FFF);

unsigned short i;
char j,k;
for(i=0; i<(1<<11); i++) {
for(j=32; j<126; j++) {
char szPassword[13];
const int cchPassword = 12;

for(k=0; k<11; k++)
szPassword[k] = (i&(1<<k))?'B':'A';
szPassword[11] = j;
szPassword[12] = 0;

unsigned short wPasswordHash = 0;
const char *pch;
wPasswordHash = 0;
if(cchPassword > 0) {
pch = &szPassword[cchPassword];
while(pch-- != szPassword) {
wPasswordHash = ((wPasswordHash >> 14) & 0x01) | ((wPasswordHash << 1) & 0x7fff);
wPasswordHash ^= *pch;
}
wPasswordHash = ((wPasswordHash >> 14) & 0x01) | ((wPasswordHash << 1) & 0x7fff);
wPasswordHash ^= cchPassword;
wPasswordHash ^= (0x8000 | ('N' << 8) | 'K');
}

printf("hash('%s') = 0x%04X\n", szPassword, wPasswordHash);
hashvalues[wPasswordHash-0x8000] = 1;
}
}

printf("Checking for unreached values ...\n");
for(i=0; i<=0x7FFF; i++)
if(hashvalues != 1)
printf("0x%04X not reached!\n",i);
printf(" ... done\n");

free(hashvalues);
return 0;
}[/src]
Output:
Code:
Expand Collapse Copy
...
hash('BBBBBBBBBBBz') = 0x8E33
hash('BBBBBBBBBBB{') = 0x9E33
hash('BBBBBBBBBBB|') = 0xEE33
hash('BBBBBBBBBBB}') = 0xFE33
Checking for unreached values ...
 ... done
D.h. es wurden keine nicht erreichbaren Werte gefunden. Die C-Implementierung ist zudem um einige Grössenordungen schneller als das VBA-Makro, der gesamte Schlüsselraum wird in ~50ms durchsucht:
Code:
Expand Collapse Copy
$ time ./excelcrack > /dev/null 

real	0m0.040s
user	0m0.037s
sys	0m0.002s
 
  • Thread Starter Thread Starter
  • #8
Öhm. Okay. Habe nur die Hälfte verstanden und gerade das Gefühl, du sprichst eine andere Sprache als ich :unknown:

Danke für deine umfangreiche Erklärung, aber das ist zu tief für mich.

hochachtungsvolle Grüße
 
Auch wenn du die Details zum Hash-Algorithmus nicht nachvollziehen kannst, führt eine einfache Überlegung zur Hash-Länge zur Erkenntnis, dass Kollisionen (d.h. mehrere Passwörter, die denselben Hash-Wert ergeben) auftreten müssen:
Wie in meinem letzten Beitrag erwähnt ist der Hash-Wert 16 Bit (4 hexadezimale Ziffern) lang, wobei nur 15 Bit effektiv verwendet werden. Daher existieren auch nur 2^15=32768 mögliche Hash-Werte - das sind vergleichsweise sehr wenige, selbst für Passwort mit nur 3 (alphanumerischen) Zeichen existieren mit (26+10)^3 = 46656 mehr Möglichkeiten. Die meisten Passwörter sind aber länger, und sie werden immer auf einen der 32768 Hash-Werte abgebildet. Folglich müssen diverse Passwörter zwingend auf denselben Wert abgebildet werden.


Speziell an diesem (sehr schwachen) Hash-Algorithmus ist jedoch, dass man, um ein Passwort (ein Urbild unter der Hash-Funktion) zu einem bestimmten Hash-Wert finden, nicht einmal alle möglichen Passwörter testen muss, da man eine sehr kleine Klasse von Passwörtern (z.B. 11 (`A`/`B`) + 1 Zeichen) definieren kann, die nachweislich alle möglichen Hash-Werte abdeckt. Bei stärkeren Hash-Funktionen wie z.B. MD5 oder SHA ist das nicht möglich.
 
  • Thread Starter Thread Starter
  • #10
Es ist also letztlich eine Frage der Wahrscheinlichkeit. Um 100% Wahrscheinlichkeit zu erreichen, genügen demnach sehr wenige Versuche. Danke für diese schöne Erklärung
 
Zurück
Oben