hỏi về giải thuật phá pass (1 người xem)

  • Thread starter Thread starter gintano1
  • Ngày gửi Ngày gửi
Liên hệ QC

Người dùng đang xem chủ đề này

gintano1

Thành viên mới
Tham gia
27/7/14
Bài viết
22
Được thích
0
chào các bác, em đọc trên mạng có đoạn code vba phá pass file excel như này mà em không hiểu họ dùng giải thuật gì, nôm na có thể nói là thử từng password nhưng các biến cho chạy từ 65 - 66 hơi khó hiểu, các bác có thể giải thích giúp em được không
Sub PasswordBreaker()
If ActiveSheet.ProtectContents = False Then
MsgBox "Sheet '" & ActiveSheet.Name & "' is unprotected!", vbInformation
Else
If MsgBox("Sheet '" & ActiveSheet.Name & "' is protected, do you want to unprotect it?", _
vbYesNo + vbQuestion, "Unprotect Active Sheet") = vbNo Then Exit Sub
Dim i As Integer, j As Integer, k As Integer
Dim l As Integer, m As Integer, n As Integer
Dim i1 As Integer, i2 As Integer, i3 As Integer
Dim i4 As Integer, i5 As Integer, i6 As Integer
On Error Resume Next
For i = 65 To 66: For j = 65 To 66: For k = 65 To 66
For l = 65 To 66: For m = 65 To 66: For i1 = 65 To 66
For i2 = 65 To 66: For i3 = 65 To 66: For i4 = 65 To 66
For i5 = 65 To 66: For i6 = 65 To 66: For n = 32 To 126
ActiveSheet.Unprotect Chr(i) & Chr(j) & Chr(k) & _
Chr(l) & Chr(m) & Chr(i1) & Chr(i2) & Chr(i3) & _
Chr(i4) & Chr(i5) & Chr(i6) & Chr(n)
Next: Next: Next: Next: Next: Next
Next: Next: Next: Next: Next: Next
If ActiveSheet.ProtectContents = False Then MsgBox "Sheet '" & ActiveSheet.Name & "' is unprotected!", vbInformation
End If
End Sub
 
... Chủ thớt cần biết mà ai cũng làm ngơ, có người còn chọc quê nữa.

Chừ chủ thớt cảm ơn tôi đi nhé!

Cảm ơn cái mốc xì. Ngược lại, tôi chần chờ không trả lời chính vì do bạn thách thức. Cỡ bạn chưa thách thức nổi tôi.

Chú: ngày mai, nếu rảnh tôi sẽ nói chuyện về lý thuyết của cái mã 65,66 này. Bây giờ thì các bạn nào muốn biết thì nên trách câu thách thức này.
 
Upvote 0
Chú: ngày mai, nếu rảnh tôi sẽ nói chuyện về lý thuyết của cái mã 65,66 này. Bây giờ thì các bạn nào muốn biết thì nên trách câu thách thức này.
Mình là dân "tay ngang" nên bất cứ thứ gì liên quan đến lý thuyết mình đều muốn lắng nghe, xem như là cách để làm đầy những lỗ hổng kiến thức
Cảm ơn bạn trước!
 
Upvote 0
Câu chuyện "giải thuật" "code thực hiện giải thuật" ở đây được dựa trên 2 lý thuyết:

1. Hầu hết các phần mềm đều mã hóa (hash) password trước khi lưu lại. Mã hóa là một hàm chuyển. Chuyện mã hóa bị trùng là chuyện có thể xảy ra. Tùy theo mức độ quan trọng, người ta dùng loại rắc rối, khả năng trùng mã dưới 1 phần tỷ (10^-10 hay thấp hơn nữa). Nhưng nếu dùng loại giản dị thì khả năng trùng mã khoảng 1 phần nửa triệu.

2. Excel căn bản chỉ là một bàng tính trải rộng, không phải là một CSDL nghiêm chỉnh (*). Việc bảo mật không quan trọng lắm cho nên MS sẵn sàng dùng loại mã hóa dạng thấp. Có nhiều lý do tại sao họ quyết điịnh làm thế:
(a) Protect khởi đầu chỉ là tránh sự sửa đổi ngoài ý muốn và tránh sự tọc mạch của người ngoài chức phận (vd nếu một nhân viên nào đó tọc mạch, giải password để làm gì đó thì trước mặt ban GĐ, nhân viên này không có lý để bào chữa rằng mình chỉ tình cờ)
(b) Như bài #16 có nói qua, MS cũng cố tình chừa cửa để giải mã dễ dàng. Ngày xưa các cơ quan xài MS Office thường ký hợp đồng bảo dưỡng và hổ trợ. Việc giải password giúp cho MS dễ đào tạo nhân viên phục vụ hổ trợ. Nên biết rằng phí tổn đào tạo một nhân viên có khả năng giải mã hạng cao không nhỏ, và khi có nghề rồi, phải trả lương cao cho nhân viên này.
(c) Như bài #16, và #17 có diễn thêm, MS chọn cách mã hóa password cho sheet là 12 ký tự đơn giản, với 11 ký tự đầu nằm trong vòng [AB], và ký tự thứ 12 nằm trong vòng ASCII đơn giản, hiển thị được; từ số 32 (dấu cách) đến 126 (dấu ngã ~). Với dạng này thì chỉ có khoảng 170 ngàn kiểu khác nhau, đối với máy tình chỉ mò trong tích tắc.

Tóm lại, code của chủ thớt đưa ra là code thực hiện cách mò từ "AAAAAAAAAAA " đến "BBBBBBBBBBB~". Cái căn bản là ở dòng "On Error Resume Next", dùng để dò hết mẫu này đến mẫu khác.
Rất tiếc là nếu lên mạng hỏi "VBA unprotect sheet without pasword" thì sẽ có hàng trăm bài, code tương tự, nhưng chủ thớt lại chọn ngay cái code dở nhất đem lên hỏi. Code đúng đắn hơn có phân biệt workbook, có đoạn code thoát ra khi đã giải xong - không phải đi đủ cả trăm ngàn lần và cuối cùng dừng ở "BBBBBBBBBBB~" (như bài #9 đoán mò)

Vì đây là code mò giải mã cho nên người ta không cần code cho minh bạch. Chứ nếu code cho chuyên nghiệp thì để mò [AB] ta có kỹ thuật giả số nhị phân, code gọn hơn nhiều.

(*) qua đến phiên bản 2013 và 2016 thì MS đã triển khai tinh năng của Excel rất cao. Với ba cái mớ PowerPivot và PowerQuery, PowerBI cung DAX functions thì Excel đã có thể liên hệ được nhiều CSDL khác nhau. Tính bảo mật cần nâng cao. Vì vậy cách giải mã trên không còn hữu hiệu. Đối với 2013 thì phải chỉnh code lại. Đối với 2016 thì tôi chưa thấy cách chỉnh nào (có cách giải mã khác, nhưng không theo nguyên tắc này)
 
Upvote 0
Vì đây là code mò giải mã cho nên người ta không cần code cho minh bạch. Chứ nếu code cho chuyên nghiệp thì để mò [AB] ta có kỹ thuật giả số nhị phân, code gọn hơn nhiều.
Thời lâu lắm rồi mình cũng nghiên cứu giải thuật của code (tham khảo trên mạng) và mình đã "tự ý" chỉnh sửa lại theo ý mình như thế này:
Mã:
Private Function IsProtected(ByVal ExlObj As Object) As Long
  Select Case TypeName(ExlObj)
    Case Is = "Worksheet": IsProtected = -1 * ExlObj.ProtectContents
    Case Is = "Workbook":  IsProtected = -2 * (ExlObj.ProtectStructure Or ExlObj.ProtectWindows)
  End Select
End Function
Mã:
Private Function Password_Remove(ByVal ExlObj As Object) As String
  Dim i As Long, j As Long, lChk As Long
  Dim tmp As String, strPass As String
  On Error Resume Next
  lChk = IsProtected(ExlObj) 'Check if worksheet or workbook is protected
  If lChk Then
    For i = 0 To 2047
      tmp = D2B(i, 11)
      tmp = Replace(Replace(tmp, 0, "A"), 1, "B")
      For j = 32 To 126
        strPass = tmp & ChrW(j)
        ExlObj.Unprotect strPass
        lChk = IsProtected(ExlObj)
        If lChk = 0 Then 'Check if password is removed
          Password_Remove = strPass
          Exit Function
        End If
      Next
    Next
  Else
    MsgBox "'" & ExlObj.Name & "'" & " is not protected!"
  End If
End Function
Mã:
Private Function D2B(ByVal Num As Long, Optional ByVal Places As Long = 1) As String
  Dim qt As Long, rd As Long, tmp As String
  qt = Num
  Do
    rd = qt Mod 2
    qt = Int(qt / 2)
    tmp = rd & tmp
  Loop Until qt = 0
  D2B = Format(Val(tmp), String(Places, "0"))
End Function
Mã:
Sub Crack()
  Dim strPass As String
  strPass = Password_Remove(ActiveSheet)
  If Len(strPass) Then MsgBox strPass, , ActiveSheet.Name
  strPass = Password_Remove(ActiveWorkbook)
  If Len(strPass) Then MsgBox strPass, , ActiveWorkbook.Name
End Sub
Code tuy có dài, thậm chí có thể tốc độ chậm hơn nhưng mình cảm thấy dễ hiểu (theo quan điểm cá nhân)
 
Upvote 0
Cảm ơn cái mốc xì. Ngược lại, tôi chần chờ không trả lời chính vì do bạn thách thức. Cỡ bạn chưa thách thức nổi tôi.

Chú: ngày mai, nếu rảnh tôi sẽ nói chuyện về lý thuyết của cái mã 65,66 này. Bây giờ thì các bạn nào muốn biết thì nên trách câu thách thức này.
Thêm 1 người chịu nóng hết nổi nên phải uống Dr. Thanh
 
Upvote 0
Thêm 1 người chịu nóng hết nổi nên phải uống Dr. Thanh
Số phận của Dr. Thanh và ông bà chủ của nó đang còn bị lâm cảnh lao lý, cùng nhận được sự khinh rẻ miệt thị của nhiều người do cách hành xử vô nhân đạo của chúng. Thế mà còn có người đi quảng cáo dùm.

Thiệt hết biết!?? đúng là "ngưu tầm ngưu, mã tầm mã".
 
Upvote 0
Số phận của Dr. Thanh và ông bà chủ của nó đang còn bị lâm cảnh lao lý, cùng nhận được sự khinh rẻ miệt thị của nhiều người do cách hành xử vô nhân đạo của chúng. Thế mà còn có người đi quảng cáo dùm
Thiệt hết biết!?? đúng là "ngưu tầm ngưu, mã tầm mã".
Lại có người nóng nữa à? Thôi thì uống vài chai Dr. Ruồi như P.S Châu vậy nhé!
 
Upvote 0
Mã:
Private Function D2B(ByVal Num As Long, Optional ByVal Places As Long = 1) As String
  Dim qt As Long, rd As Long, tmp As String
  qt = Num
  Do
    rd = qt Mod 2
    qt = Int(qt / 2)
    tmp = rd & tmp
  Loop Until qt = 0
  D2B = Format(Val(tmp), String(Places, "0"))
End Function

Hàm này dùng nhiều toán tử mod, khong được hiệu quả lắm. Toi mạn phép sửa như vầy:

Mã:
Function Dec2Bin(ByVal Num As Long, Optional ByVal Places As Long = 1) As String
'  hàm dùng cách so sánh bit để đổi số nguyên thành dạng chuỗi nhị phân
  Dim bit As Integer, bitOn As Long
  Dec2Bin = String(Places, "0")
  bit = Places
  bitOn = 1
  Do While bitOn <= Num And bit > 0
    If bitOn And Num Then ' nếu ứng với bit của số thì set bit
      Mid(Dec2Bin, bit, 1) = "1"
    End If
    bit = bit - 1
    bitOn = bitOn * 2 ' dời số 1 sang 1 bit
  Loop
End Function

Lưu ý là hàm sẽ dừng đúng chỗ độ dài Places. Những bits lớn hơn đó sẽ bị cắt bỏ. Nếu muốn nối dài như hàm của bạn thì sửa như sau:
Mã:
  Do While bitOn <= Num
    If bit < 1 Then
      bit = 1
      Dec2Bin = "0" & Dec2Bin
    End If
    If bitOn And Num Then
      Mid(Dec2Bin, bit, 1) = "1"
    End If
    bit = bit - 1
    bitOn = bitOn * 2
  Loop
 
Upvote 0
Nói chuyện ngoài lề nhiều quá! Mọi người nên biết dừng đúng lúc và tập trung vào chuyên môn giùm
Cảm ơn!
 
Upvote 0
Suy luận logic kiểu lập trình viên, tuy nhiên trật lấc :) :)

Đây là góc lập trình của diễn đàn Excel, suy luận lô gic lập trình viên thì không thích ứng chỗ nào?

Nếu bạn cố chủ ý tranh luận theo lô gic "cưỡng bức" như sau thì tại đây tôi nhận thua kém bạn vậy. Tôi chưa hề học qua loại lô gic "cưỡng bức" này và cũng không hề có ý muốn học.

Hình như tác dụng của đoạn code này là làm rối loạn cơ chế protect của Excel để cưỡng bức nó phải unprotect chứ không phải thử khớp mật khẩu.
 
Upvote 0
Hàm này dùng nhiều toán tử mod, khong được hiệu quả lắm. Toi mạn phép sửa như vầy:

Mã:
Function Dec2Bin(ByVal Num As Long, Optional ByVal Places As Long = 1) As String
'  hàm dùng cách so sánh bit để đổi số nguyên thành dạng chuỗi nhị phân
  Dim bit As Integer, bitOn As Long
  Dec2Bin = String(Places, "0")
  bit = Places
  bitOn = 1
  Do While bitOn <= Num And bit > 0
    If bitOn And Num Then ' nếu ứng với bit của số thì set bit
      Mid(Dec2Bin, bit, 1) = "1"
    End If
    bit = bit - 1
    bitOn = bitOn * 2 ' dời số 1 sang 1 bit
  Loop
End Function

Lưu ý là hàm sẽ dừng đúng chỗ độ dài Places. Những bits lớn hơn đó sẽ bị cắt bỏ. Nếu muốn nối dài như hàm của bạn thì sửa như sau:
Mã:
  Do While bitOn <= Num
    If bit < 1 Then
      bit = 1
      Dec2Bin = "0" & Dec2Bin
    End If
    If bitOn And Num Then
      Mid(Dec2Bin, bit, 1) = "1"
    End If
    bit = bit - 1
    bitOn = bitOn * 2
  Loop
Mới xem sơ qua nhưng chưa "kịp" hiểu. Để về nghiên cứu lại
Có điều bạn không nên đặt tên hàm là Dec2Bin vì sẽ trùng với hàm có sẵn của Excel (vì thế nên tôi phải đổi thành D2B)
Cũng xin nói thêm vì sẽ có người thắc mắc tại sao Excel đã có sẵn hàm Dec2Bin rồi sao không dùng luôn mà phải viết thêm D2B để làm giống gì? Bởi Dec2Bin của Excel có hạn chế, nó chỉ tính được đến Num= 511 và Places = 10 mà thôi
 
Upvote 0
Có điều bạn không nên đặt tên hàm là Dec2Bin vì sẽ trùng với hàm có sẵn của Excel (vì thế nên tôi phải đổi thành D2B)

Không để ý. Cảm ơn nhắc nhở.

Cũng xin nói thêm vì sẽ có người thắc mắc tại sao Excel đã có sẵn hàm Dec2Bin rồi sao không dùng luôn mà phải viết thêm D2B để làm giống gì? Bởi Dec2Bin của Excel có hạn chế, nó chỉ tính được đến Num= 511 và Places = 10 mà thôi

Bạn vẫn có thể viết hàm nới thêm cho nó. Có lẽ đó là chủ ý của MS, để cửa cho bạn nới rộng đến số lớn hơn Long (tức là Double)

Giải thuật:
dùng vòng lặp mod và chia 512. Cứ phần mod thì gọi Dec2Bin để tính. Và cứ mỗi đoạn thì nối chuỗi lại.
(dùng đệ quy có lẽ đẹp mắt nhất, nhưng e hơi khó hiểu)
 
Lần chỉnh sửa cuối:
Upvote 0
Hàm D2B ở trên hình như chạy không đúng lắm khi con số lên trên 32768. Cách test dễ nhất là bạn bảo nó tính bất cứ con số nào lớn hơn 32768 và là số lẻ. Số lẻ đổi ra Binary thì phải có số 1 cuối cùng, nhưng hàm sẽ cho ra số 0 cuối.
Sau khi xem kỹ lại thì tôi đoán có lẽ do dòng này
D2B = Format(Val(tmp), String(Places, "0"))
Hàm Val đổi chuổi thành số (float). Số trong hệ thống Windows chỉ chính xác đến 15 đơn vị. Các số lớn hơn 32767 dài 16+ bits. Như vậy các bits sau 15 sẽ chỉ toàn 0.

Tôi đề nghị sửa:
If Len(tmp) >= Places Then
D2B = tmp
Else
D2B = Right(String(Places, "0") & tmp, Places)
End If
 
Upvote 0
Tôi thì tôi sửa như thế này
PHP:
Str = "AAAAAAAAAAA"
Do
    For i = 32 To 126
        ...
        If ... Then Exit Sub
    Next
    Mid(Str, InStrRev(Str, "A")) = "BAAAAAAAAAA"
Loop
Không biết có nhanh không nhưng thấy gọn hơn.
 
Upvote 0
Bạn nên thêm phần thoát nếu có rắc rối. Nếu không thì có thể vòng lặp chạy hoài không dứt.

If Str = "BBBBBBBBBBB" Then Exit...

Điểm thứ hai, đối với chương trình phức tạp độ này, dùng lệnh Exit Sub để thoát vòng lặp có hơi nguy hiểm. Lắm khi ta cần dọn rác trước khi thoát Sub.

Một trong những mẹo vặt để thoát một lúc nhiều vòng lặp FOR (như code nguyên thuỷ của chủ thớt) là dùng vòng lặp giả

Do ' vòng lặp giả
for a: for b: for c: ...: for n
if (thoả điều kiện) then Exit do ' vì chỉ có vòng ngoài cùng là DO cho nên lệnh này thoát tất cả vòng for
next a: next b: next c: ...: next n
Loop Until True ' vòng lặp giả, vì điều kiện là true cho nên nó chỉ chạy 1 lượt chư không lặp lại
 
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom