Tải bản đầy đủ (.pdf) (6 trang)

Hacker Professional Ebook part 129 docx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (135.42 KB, 6 trang )

Tutorial is writed by anarchriz
Translated by kienmanowar


CRC and how to Reverse it
A CRC Tutorial & The c00l way to Reverse CRC

Lời mở đầu :

Bạn luôn luôn muốn biết rằng vậy chính xác CRC nó là cái gì ? Và cũng muốn biết
rằng nó thực hiện như thế nào ? Thậm chí bạn cũng đã từng nghĩ ra nhiều cách để
reverse CRC, nhưng chưa có cách nào thành công? Và bạn cũng đã từng Patch một
đoạn code mà bản thân đoạn code đó không được cảnh báo là CRC ? Thậm chí bạn
cũng đã muốn viết một số mẹo anti-antivius để làm cho CRC kiểm tra một cách vô
ích ? Tốt , vậy thì bạn đã tìm đến đúng chỗ rồi đó !

Introduction :

Bài viết này bao gồm có một bài hướng dẫn về CRC và một bài nói về cách để làm
thế nào thay đổi CRC hay nói cách khác là reverse CRC . Có rất nhiều các Coders
/Reversers không biết một cách chính xác CRC hoạt động như thế nào và hầu hết
không ai biết làm thế nào để reverse nó , trong khi những kiến thức cần phải biết
về CRC thì lại rất quan trọng. Dó đó trong tut đầu tiên này sẽ chỉ cho bạn biết làm
thế nào để tính CRC (cách thường dùng nhất) , bạn có thể sử dụng nó như một dữ
liệu hoặc là code protection. Phần thứ hai là phẩn reverse (đây là phần chính) , sẽ
giúp bạn làm thế nào để reverse CRC-32 , bạn có thể sử dụng các kiến thức trong
phần này để phá vỡ các CRC protection trong chương trình hay các chương trình
khác ví dụ như anti-virus.Có thể đây là một cách hữu dụng và thiết thực nhất mà từ
đó tôi có thể ‘correct’ về CRCs cho bạn , nhưng tôi cũng e rằng chúng cũng không
thể giải thích được là chúng đang làm cái gì.
Tôi cũng muốn cảnh báo với các bạn rằng , từ đây sẽ có một số hàm được sử dụng


trong bài viết này. Điều này sẽ không làm ảnh hưởng đến bất kì ai , vì ai cũng có
thể hiểu được chúng một cách dễ dàng ngay cả khi chúng ta chỉ là những avarage
Coders or Reversers. Tại sao ư, đơn giản thôi vì nếu như bạn không biết được tại
sao hàm đó được sử dụng trong CRC thì tôi khuyên bạn rằng bạn nên click chuột
vào nút ‘x’ ở phía trên bên phải của màn hình. Vì vậy , tôi cho rằng các bạn đã nắm
chắc các kiến thức cơ bản về số nhị phân và các phép toán dùng trong số nhị phân.

Tutorials :
Part1 : CRC Tutorial, what it is and how to calculate it
Cyclic Redundancy Code or CRC

-Tất cả chúng ta biết về CRC . Thậm chí nếu bạn không nhắc lại , bạn sẽ nhớ lại về
những thông báo đã từng làm cho bạn bực mình của các chương trình nén thông
dụng như RAR , ZIP hay là những chương trình nén khác bắn ra khi một file nào
đó bị hư hỏng tại vì bad connections hoặc là những đĩa mềm bị hỏng (!@#$%
floppies) . CRC là một giá trị được tính toán thông qua một đoạn dữ liệu , lấy ví dụ
với mối file khác nhau thì thời gian nén sẽ khác nhau . Khi một archiver đang
unpacking một file , nó sẽ đọc CRC và sẽ kiểm tra CRC này với CRC mới đã tính
được của file đã được giải nén ( trong trường hợp này chắc là file sau khi
Unpacking). Nếu chúng khớp nhau , thì đó là dấu hiệu tốt chứng tỏ các file giống y
hệt nhau. Với CRC-32 , cơ hội để nhận biết ra sự khác nhau, sự thay đổi trong dữ
liệu là 1/2^32 (Trích dẫn : With CRC-32,there is a chance of 1/2^32 of the check
failing to recognize a change in data.)

Hầu hết mọi người đều nghĩ rằng CRC là từ viết tắt của Cyclic Redundancy
Check . Nếu quả thực CRC là từ viết tắt của Cyclic Redundancy Check thì lại có
rất nhiều người sử dụng không đúng thuật ngữ này. Nếu nói như vậy thì bạn không
thể nói CRC của một chương trình là 12345678 . Mọi người cũng thường xuyên
nói một chương trình cụ thể nào đó có một CRC check, không phải là Cyclic
Redundancy Check . Nhưng nói tóm lại là CRC là từ viết tắt của Cyclic

Redundancy Code chứ không phải là Cyclic Redundancy Check.

Vậy thì việc tính toán được thực hiện như thế nào ? Well , ý tưởng chính là để
quan sát , hiểu rõ một file khi mà một chuỗi lớn các bít được chia bởi nhiều số , mà
sẽ cho bạn một số dư đó là CRC!. Bạn sẽ luôn có được một số dư ( cũng có thể là 0
) . Ví dụ (9/3=3 số dư =0 ; (9+2)/3=3 số dư =2).

Nhưng ở đây việc chia các bít được thực hiện sẽ có những khác biệt nhỏ . Phép
chia là việc lặp đi lặp lại của ( x lần ) phép trừ một số ( số chia ) từ một số mà bạn
muốn chia, và từ đó sẽ cho bạn một số dư . Nếu bạn muốn có lại số ban đầu thì bạn
có thể nhân kết quả với số chia hoặc có thể cộng (x lần ) số chia với nhau và cuối
cùng là đem kết quả đó cộng với số dư sẽ cho ta số bị chia ban đầu.

( Ok sau khi dịch xong đoạn này mình có thể lấy ví dụ cho các bạn như sau :
1) 11/3 = 3 số dư = 2 > vậy để có được số ban đầu là 11 ta thực hiện như sau :
lấy kết quả của phép chia (= 3) đem nhân với số chia ( = 3) được bao nhiêu cuối
cùng đem cộng với số dư thu được (= 2) . Vậy cuối cùng 11 = 3*3 + 2.
2) Cũng với trường hợp trên nhưng mình lấy ví dụ là phép trừ :
11 – 3 = 8
8 - 3 = 5
5 – 3 = 2
2 – 3 = ke ke đến đây không trừ nữa
Các bạn có thể thấy ở trên là việc lặp đi lặp lại của phép trừ , mà ở đây ta có số lần
thực hiện là ( x =3 lần) . Do đó để có được số ban đầu ( = 11 ) thì bạn thực hiện
như sau : chúng ta sẽ cộng (x = 3 lần) số chia ( = 3 ) với chính nó , kết quả của
phép cộng này được bao nhiêu thì chúng ta đem cộng với cái số dư kia ( = 2 ) . Vậy
tóm lại : 11 = 3 + 3 + 3 + 2.
).

Ok tiếp tục , vậy thì việc tính toán CRC cũng sử dụng một cách đặc biệt của các

phép toán trừ và cộng . Lấy ví dụ , có một số mới. Trong quá trình tính toán số nhớ
cho mỗi bít thì có một số bị mất. Bạn sẽ xem hai ví dụ sau đây để hiểu rõ hơn về
phép cộng không có nhớ và phép cộng có nhớ khác nhau như thế nào . Ví dụ thứ
nhất dưới đây chỉ là việc thực hiện một phép trừ bình thường không có gì cả ,
nhưng các bạn hãy tập trung vào ví dụ 2 & 3 đó là các ví dụ về việc bit carry ( bít
nhớ) bị “forgotten”.
&.dnm=ea6d.jpg
Trong ví dụ (1) , cột thứ hai tính từ bên phải sang sẽ thực hiện phép tính là 0 – 1 =
-1 , vì vậy nó sẽ phải mượn một (vay một ) bít từ bít ngay cạnh nó và điều này sẽ
cho bạn một phép tính như sau (10+0) – 1 = 1 ( như bạn thấy phép tính này cũng
tương tự như khi bạn trừ trên giấy đối với các số ở hệ 10 ( thập phân )). Trong hai
ví dụ đặc biệt tiếp theo là (2) & (3) , phép tính 1 + 1 sẽ cho kết quả là 10 , vậy bít 1
sẽ chính là bít nhờ và bít này sẽ được chuyển cho bít bên cạnh khi ta thực hiện
phép tính tiếp theo. Và như các bạn đã thấy , bít này sẽ bị mất đi khi chúng ta tính
toán ở bít cuối cùng . Đối với trường hợp đặc biệt 0 - 1 , thì câu trả lời sẽ là = -1 ,
vậy thì điều gì sẽ tác động lên bít ngay bên cạnh nó ( xem ví dụ 1) . Giá trị này
cũng bị mất đi . Nếu bạn biết một chút ít về lập trình , thì nó chính là phép toán
XOR.

Tiếp theo chúng ta sẽ xem một ví dụ về phép chia :
Trong phép tính thông thường :
&.dnm=ea6d.jpg
Trong phép tính của CRC :
&.dnm=f8b1.jpg
Kết quả của phép chia ở đây không quan trọng , và không hiệu quả để nhớ bởi vì
nó sẽ chỉ là một cặp các bít nhỏ hơn bitstring nơi mà bạn muốn tính toán theo CRC
. Vậy thì điều quan trọng chính là số dư ! Đó là vấn đề phải bàn luận ,nói nhiều
nhất khi chúng ta tìm hiểu về file gốc . Đó là điều cơ bản về CRC.

Going over to the real CRC computation


- Để thực hiện một phép tính CRC chúng ta phải chọn một số chia , từ bây giờ
chúng ta gọi số này là “poly’” . Chiều rộng (W) của một poly chính là vị trí của bít
cao nhất. Vì vậy chiều rộng của poly 1001 là 3 , chứ không phải là 4 . Chú ý rằng
bít cao nhất luôn luôn là một , khi bạn đã chọn chiều rộng của poly bạn chỉ được
chọn một giá trị cho những bít W thấp hơn .
Nếu chúng ta muốn tính toán CRC thông qua bitstring , chúng ta phải chắc chắn
rằng tất cả các bít đều được xử lý. Vì vậy chúng ta cần phải thêm các bít 0 tương
ứng với chiều rộng W mà ta tìm được vào sau bitstring . Trong ví dụ 3 ở trên , thì
bitstring chính là 1111 . Sau đây chúng ta sẽ xem thêm một ví dụ nữa :
&.dnm=9fa0.jpg
Có hai vấn đề quan trọng cần phải nói ở đây:
- Chỉ có bít cao nhất là bít một trong bitstring , chúng ta XOR nó với poly , còn
trường hợp khác chỉ là việc chúng ta dịch bitstring đi một bít về bên trái.
- Mục đích của các vòng XOR là , nó chỉ được XOR với các bit thấp của W bits,
bởi vì bít cao nhất luôn cho giá trị 0 .
(Ặc ặc các bác cố gắng hiều cái ví dụ trên )
To be continue :)

Tut Continue
Going over to a Table-Driven Algorithm

Tất cả các bạn đều hiểu rằng các thuật toán dựa trên việc tính toán từng bít sẽ rất
chậm và không hiệu quả. Nó sẽ có hiệu quả cao hơn nếu như bạn có thể tính toán
nó dựa trên việc tính toán theo từng byte.Do đó chúng ta có thể đồng ý các poly sẽ
có độ rộng là 8 bít ( đó chính là byte) . Bạn hãy tưởng tượng nó trong ví dụ sau với
poly có chiều rộng là 32 bít (W = 32).

&.dnm=d55c.jpg


Đó là một thanh ghi bạn sử dụng để lưu trữ kết quả tạm thời của CRC , ở đây tôi
gọi nó là thanh ghi CRC ( CRC register ) hoặc chỉ là một thanh ghi kể từ bây giờ.
Bạn đang dịch chuyển các bít từ bitstring bắt đầu từ phía bên phải , và các bít được
dịch ra ngoài từ phía bên trái ( tức là theo chiều mũi tên như thế này < ) . Khi
mà bit vừa được dịch ra ngoài từ phía bên trái là một , thì toàn bộ thanh ghi được
XOR bằng lower W bits của poly ( in this case 32) . Trên thực tế , chúng ta đang
thực hiện một cách tương tự , chính xác như là phép chia đã thực hiện ở trên.
Vậy thì ( như tôi đã nói ) nếu chúng cùng lúc dich chuyển một nhóm bít (shift in &
out ) thì sao. Hãy xem một ví dụ của 8 bit CRC với việc dịch chuyển 4 bit cùng
một lúc (shift in & out ) :
Quote:
The register just before the shift : 10110100
Then 4 bits (at the top) are shifted out at the left side while shifting 4 new
bits in at the right side. In this example 1011 is shifted out and 1101 (new)
is shifted in.

Then the situation is this:
8 bits currently CRC/Register : 01001101
4 top bits just shifted out : 1011
We use this poly : 101011100, width W=8
Bây giờ chúng ta tính toán như bình thường với giá trị mới của thanh ghi :

&.dnm=bbb1.jpg

Bây giờ bạn có thể thấy rằng các bít ở vị trí topbits đều bằng 0 . Vì vậy trong
trường hợp này chúng ta sẽ không phải tiếp tục XOR topbits với Poly nữa .
Bạn cũng có thể có được một kết quả tương tự như trên bằng việc thực hiện các
thao tác sau : Nếu đầu tiên bạn XOR (*1) với (*2) và kết quả với thanh ghi . Kết
quả này có được là bởi vì vòng XOR này sẽ được thực hiện như sau : (a XOR b)
XOR c = a XOR (b XOR c).


&.dnm=2fa3.jpg

Bạn hãy quan sát nhé! Sau khi tính toán theo cách trên chúng ta đã có được một kết
quả tương tự. Bây giờ kết quả mà chúng ta có được (*3) sau khi XOR hai Poly với
nhau là rất quan trọng, bởi vì với topbits là 1010 thì chúng ta luôn luôn có được giá
trị của (*3) = 10111100 (only the lower W=8 bits) . Điều này có nghĩa là bạn có
thể thực hiện tính toán trước giá trị XOR values cho mỗi tổ hợp của topbits. Chú ý
rằng giá trị của topbits sẽ luôn là 0 sau khi thực hiện lặp lại các vòng XOR (this
must be because the combination of XORring leads to it.).

Bây giờ chúng ta lại quay trở lại với hình minh họa thứ 1 ((figure 1).Với mỗi giá trị
của byte đầu tiên (8 bits) vừa mới được dịch ra ngoài , chúng ta có thể tính tóan
trước được một giá trị . Trong trường hợp này nó sẽ là một bảng bao gồm 256
(2^8) phần tử của doube word (32 bits) (Bảng CRC-32 nằm ờ phần phụ lục _ tôi sẽ
đưa ra sau ).

×