2013年5月29日 星期三

關於客戶端保護技術的一些嘴砲(無技術含量)

前陣子雖然發了一些前端工程的小伎倆文章,不過最近又跑去研究了一下逆向工程的技術。今天就來說說最近研究的心得吧(本篇為基礎概念,沒甚麼實質技術含量)。

客戶端保護是甚麼? 簡單的說就是防止別人破解,竄改程式的一種技巧。像以前的單機遊戲有的要問密碼,或確認原版光碟,如果程式沒保護的話,透過逆向工程,大概半小時就可以把這些保護搞定了。

現在用最多保護技術的程式,大概就是線上遊戲了吧。主要目的是為了防止外掛,市場上主流的保護系統,大概有早期就出現的nProtect,一直到現在安博士和騰訊的TenProtect。每家用的伎倆大概也都差不多,大概就是加殼及Anti-Debug。加殼的部分是遊戲公司自己處理,還是這些保護廠商提供,其實我也不是很明瞭,總之這兩者大概算是不一樣的技術,先來說說加殼吧。

甚麼是加殼?
這是一種比較早期就有的保護技術,透過把原來的程式碼加以壓縮、加密、甚至用虛擬機技術保護起來,使破解者難以用靜態分析看到原始程式,也就難以找到要破解的地方。
不過,程式載入後總是得解密才能執行,破解者可以用一些技巧等到程式解密完成後,直接把解密過的程式存檔,就可以為所欲為啦,這就是俗稱的脫殼。

不過使用虛擬機技術的殼就沒這麼簡單,他有些原始碼已經被混淆,藏在一大堆垃圾代碼和無止盡的跳躍指令中,但這也只是加深破解者的解讀程式的難度,並不會真正阻止程式被解讀。

所以說到底,加殼只防君子不防大牛,所以NP、HS、TP才會紛紛崛起

甚麼是Anti-Debug?
對岸的人們稱為反調戲....反調適才對,總之就是透過各種技巧,使得其他程式無法讀寫該程式的記憶體,並且讓debugger無法附加到該程式,這也是現在外掛和保護大鬥法的主戰場。

一般來說,透過一些window API,我們可以任意存取系統中其他程序的資料,透過debugger的附加,更可以了解該程序如何運作。那這些保護系統,就是專門癱瘓掉這些API的高手。現在大多數的保護系統都會使用驅動程式級的保護,直接修改系統的kernel,阻止一些記憶體存取,和debugger相關的API,使得強如CheatEngine、OllyDebugger都無法對該程序進行存取。可是道高一尺、魔高一丈,如果這些保護搞的把戲都一一被揭穿,那麼破解者也可以寫個驅動程式修改kernel,使得前者的修改失效。不過到了這邊,所需要的技術就會比脫殼更困難許多。

以上是針對32位元系統,64位元系統又是另外一種保護的方式,這邊我也還沒研究到,就先不提。

必要技能
現在遊戲的保護都是加殼和Anti-Debug一起上的,不過還是外掛一堆。而甚麼都沒加的也是有...這種的外掛都滿到流出來了...

關於破解和保護的技術,學校不會教,老師也不會,那要到哪邊學呢?這邊我列出一些必要的技能好了

  1. 組合語言(對岸稱為匯編),要像母語一樣熟哦,對一些常改的機械碼也要有些認識
  2. 使用debugger經驗和技巧,這邊指的debugger是OllyDBG、WinDBG這類系統。像甚麼斷點、硬體斷點甚麼的要像吃飯一樣流暢
  3. 對系統的了解,這點是我的弱項,不過網路上許多牛人分享各種破解知識,多看多學習,總會精進
  4. 編程能力,不管前三項再強,不會寫程式大概就只能當當講師。提供保護的人,自然要能夠寫程式來實現保護,而破解的人,當然也要寫一些工具來突破前者的保護囉
總結
逆向是一件有趣的事,懂的人一定有飯吃,不懂的人了解一下概念也不錯。如果公司有推出甚麼厲害的產品,要了解不管甚麼工具都無法保護程式,只要有人有心破解甚麼都擋不住。

畢竟跑在人家的作業系統、用人家的記憶體,吃人家的CPU,自然要脫光光給人看了

所以真的有甚麼一定要保護的東西,還是多想想法子吧,像是放在Server端甚麼的

最後,祝大家的程式都有被破解的價值囉

2013年5月18日 星期六

AngularJS中,如何使ng-click事件在特定條件下無法觸發(disabled)?

有時候我們希望某些按鈕是呈現disabled的狀態,同時ng-click事件也不能被觸發。要做到這點,有兩個方式:

首先要先指定一個angular變數作為判定是否disabled,這邊就用disabled這名字當變數好了

第一個方式是在ng-click事件動手腳,將事件改成

 <button ng-click="disabled || some_func()">Click Me</button>

如此一來,當disabled為true時,就不會觸發some_func()

另外一個方式,應該是比較正規的方式,是加上標籤ng-disabled,例如

<button ng-disabled="disabled"  ng-click="some_func()">Click Me</button>

這邊借用一下別人的測試範例連結,有簡單清晰的代碼可供參考

AngularJS簡介,以及和現有網站的漸進式整合:如何從DOM更新資料給AngularJS


最近在保哥的部落格看到AngularJS的大力推薦,
雖然最近內部網站開發的事情已經忙的不可開交,但看了官網介紹後忍不住要偷偷地試用一下。

簡單的介紹一下,AngularJS提供了一個雙向的data-binding。
只要在html碼中註記什麼地方要使用哪個變數,從此兩者就互相同步更新,不需要寫任何代碼
這樣的好處是什麼呢?就是從不用再寫一大堆這種東西

var some_value;

some_value = $("#aaa").val(); //for reading
$("#aaa").val(some_value);    //for writing

在AngularJS只要這樣,資料就建立了雙向繫結,從此不用寫一堆code囉

<input id="aaa" ng-model="some_value"/>


另外一個好處,就是他的設計原則是強制做資料、代碼分離,這個比較抽象

詳細資料還請看AngularJS官網,也可以去保哥的部落格看看介紹

AngularJS很好很強大,但我該怎麼應用在現有網站呢?

以我現在正在開發的網站為例,雖然很想體驗一下AngularJS的威力,但我已經有一個現有的javascript資料讀寫系統,,但總不能整個打掉重寫吧。以下先假設讀者已經把AngularJS網站教學跑過一遍,稍微有點熟悉了。

其實最主要的,就是要把資料傳給AngularJS的scope,之後用AngularJS做的部份就可以使用該資料了。這邊假設我原有系統存在一個SelectedId變數,並且根據使用者選取而改變,但是這是一個普通的JavaScript變數,無法在AngularJS的code中直接存取,也不提供data-binding功能,那麼只要我再更新這個值的時候,執行以下程式


$("html").scope().$apply(function (scope) {

            scope.SelectedId = SelectedId;

        });


之後就可在AngularJS的scope中使用SelectedId 囉

JQuery 2.0 存在Bug? 請小心服用

今早開始試用AngularJS,並且整合到舊版的系統中
忙了一個早上,突然驚覺網頁上Kendo UI的Grid的Header排版全都亂了!
同時喪失resize等各種功能 清查發現該header的Html碼竟然產生錯了,
原本應該是這樣的代碼
   
<colgroup>
   <col style="width:150px">
   <col style="width:50px">
</colgroup>

竟然變成了
   
<colgroup>
   <colgroup>
      <col style="width:150px">
      <col style="width:50px">
   </colgroup>
</colgroup>
花了一些時間清查測試後,最後發現Kendo UI中的一行代碼出錯

 

 colgroup = $("").append($(new Array(groups + 1).join('') + cols.join(""))); 



這行代碼在JQuery 2.0中會產生錯誤的資料,在1.9.1就正常運作 看來,要試新貨,還是要多小心

2013年5月13日 星期一

如何使用Json.Net轉換舊版本的DataSet中DataRow

好好好,我知道現在流行的是Entity Framework - Code First ,很屌,屌爆了(半夜出BUG屌就真的得爆了?)。不過總是有些老Code還得維護,在這些Code上西天之前,搞不好還得先上個雲端,是吧?不雲端一下老東西還賣的出去嗎?老頭子們都陣亡了,難道要小鬼們重新寫這些糾結到纏綿斐撤的Code?

好,想當年ORM的一哥,xxxxDataSet.xsd也曾在江湖上飭剎風雲,今天老闆要你把它上雲端,你上不上?還好現在都很人性的,隨便拿個Json序列化一下就能交差了事,應該是這樣的吧。大概就是先這樣這樣,在那樣那樣....

            var ds = new Database1DataSet();
            var table = ds.DataTable1;
            string json = JsonConvert.SerializeObject(table.Rows);    

打完收工!,先來Run一下,果然很快就ok啦,這時候拿複雜一點有關連的資料表,且資料庫裡面已經有資料的系統來Run一下,咦?怎麼卡住了!???

其實是因為Typed DataSet自動產生的DataRow包含了太多不必要的連結跟參考,但是那些DataRow類別是自動產生的,並不適合直接修改。其實這時候有另外一種方式,直接看Code比較快
//這行當然是寫在某個函式中,這邊簡化讓他空中飄吧
string json = JsonConvert.SerializeObject(table.Rows, new JsonSerializerSettings()
            {
                ContractResolver = new DynamicContractResolver(),                       
            });


public class DynamicContractResolver : DefaultContractResolver
{
    protected override IList< JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        IList< JsonProperty> properties = base.CreateProperties(type, memberSerialization);

        var ignoreProperties = new string[] { "ItemArray", "Table", "RowState", "RowError", "HasErrors" };
                
        properties =
            properties.Where(p => !p.PropertyName.EndsWith("Row") && !ignoreProperties.Contains(p.PropertyName)).ToList();

        //這邊可以自行在略過一些不必序列的資料條件,這邊範例是結尾為Date的欄位也不要序列化
        properties = properties.Where(o => !o.PropertyName.EndsWith("Date")).ToList();

        return properties;
    }
}
這麼一來就可以略過DataRow中不必要的屬性,老DataRow也能上天堂啦

順道一提,如果DataRow轉換上會產生Exception,可以這樣處理
                return JsonConvert.SerializeObject(table.Rows, new JsonSerializerSettings()
                    {
                        ContractResolver = new DynamicContractResolver(tableName),
                        Error = (object o, ErrorEventArgs e) =>
                        {
                            //這邊放錯誤處理函式
                            e.ErrorContext.Handled = true;
                        }
                    });
不過如果有大量錯誤,將會造成序列化非常非常非常的慢哦,最好用別種方式解決

2013年5月12日 星期日

關於Windows Azure網站功能簡易心得

剛接觸Windows Azure的人,如果要架設網站,可以選擇使用網站(WebSites)、雲端服務(CloudApp)、以及虛擬機器。
虛擬機器的差異很明顯了,但是大家一定會納悶,WebSite和CloudApp有什麼差異性?

經過了一些比較和測試,這邊簡單說明一些我發現主要差異的地方
  1. Caching
    CloudApp可以分為Web Role和Worker Role,可以分別擴充,也支援各自的caching,在微調上面有較大的自由度。而WebSite則沒有caching功能,要用的話得額外開一個CloudApp做Cache使用,或使用舊版介面中很貴的Sharing Cache。
  2. CPU限制
    WebSite中有嚴格的CPU時間使用限制,一般是每日4小時。其中最麻煩的就是短期間的CPU限制,每5分鐘只能使用2.5分鐘的CPU時間,有時候deploy完網站就爆了,即使使用付費的共用模式,使用者開始成長後,很容易就CPU炸了。不過沒關係,拿出$$$,切換成較貴的保留模式就無此限制囉。CloudApp一開始就是獨立運作,所以也沒有CPU使用限制。
  3. 效能比較
    這邊只比較最便宜的部份,WebSites最便宜的保留模式大小為小型,單核心,1.75GB RAM(即使是免費或共用模式,應該也同規格)。而CloudApp最便宜則為超小型,共用核心,768MB RAM。實際Run一個簡單網站來看,可以發現超小型的CPU跑起來比小型的慢很多,所以超小型的CloudApp大概不能列入商用考慮囉。CloudApp也可以跑小型,定價比WebSites便宜一點點,但WebSites目前為預覽期間有打折,就先頂著用吧。
    最新定價方案請參閱官方網站 
  4. Deploy速度
    目前CloudApp最大的問題,就是Deploy超慢。好像會建立某種影像檔後上傳,我的小專案更新一次就要20分鐘。而WebSites則一兩分鐘搞定。
  5. Socket、WebSocket、WCF中的net.tcp支援
    WebSites目前都不支援,聽說CloudApp可以支援,不過沒有測試過囉
簡單來說,WebSites比較簡單易用,不需要什麼特異功能的網站很適合使用。如果需要一些微調、Caching、Worker Role、Socket等等,才會需要用到CloudApp吧。

其他部分
  • Azure Storage 特性
    • Table
      可以直接在網站中使用,也可寫WinForm程式使用。Table每個物件限制1MB,每個屬性限制64KB,不太方便存大的物件。
    • Blob
      大的物件最好用Blob,Blob必須先到Azure網頁控制台建立Container後才能使用。除了儲存程式資料外,還可以放靜態檔案如圖片,供網頁使用。
  • Azure Storage 開發
    • 本機模擬器的連線字串無法被Parsing,必須直接取得物件中的Development Instance用
    • Azure Storage API出錯時,Exception無法表示正確錯誤,需先把連線的https改成http,並用wireshark之類的軟體攔截http封包監看實際錯誤訊息。
    • Azure Storage如要加上Custom Domain,必須先切換到舊版的Management Portal才能用
  • CloudApp
    • 如果使用超小型的CloudApp,必須修改設定中本機儲存體大小,內定為20000MB,要改成19,480 MB(6,144 MB 保留給系統檔案),否則上傳會失敗。
本文撰寫於2013/5/12,如果時光久遠,請重新到微軟網站比較新版差異。