Trao đổi với tôi

http://www.buidao.com

5/31/10

[MASM] Lệnh và ASM cơ bản

Lệnh và ASM cơ bản:




MOV DTS, SRC: Chuyển giá trị từ toán hạng nguồn vào toán hạng đích

PUSH SRC: Cất giá trị toán hạng nguồn vào đỉnh ngăn xếp

PUSHF: Chuyển giá trị cờ vào đỉnh ngăn xếp

POP DST: Chuyển giá trị từ đỉnh ngăn xếp vào toán hạng đích

POPF: Chuyển giá trị từ đỉnh ngăn xếp vào cờ

XCHG DST, SRC: Chuyển đổi giá trị giữa 2 toán hạng

LEA REG, mem: Đưa địa chỉ Offset của toán hạng nguồn vào thanh ghi đích

ADD DST, SRC: Cộng toán hạng nguồn và đích. Kết quả lưu ở toán hạng đích

ADC DST, SRC: Tương tự và cộng thêm cờ CF

INC DST: Tăng 1 cho toán hạng đích

SUB / SBB / DEC: Tương tự cho phép trừ

NEG DST: Bù 2 giá trị toán hạng đích.

CMP DST, SRC: So sánh giá trị toán hạng đích và toán hạng nguồn. Tác động vào cờ, giá trị 2 toán hạng không thay đổi.

MUL / IMUL DST , SRC: Phép nhân không / có dấu. Kết quả lưu ở toán hạng đích.

DIV / IDIV DST , SRC: Tương tự cho phép chia. AX : Số nguyên, DX số dư.

NOT DST: Đảo bit.

AND DST , SRC: Phép và logic giữa toán hạng đích và nguồn. Kết quả trả về ở toán hạng đích.

OR DST, SRC: Phép hoặc logic

XOR DST, SRC: Exclusif OR ( Bit của kết quả bằng 1 nếu giá trị 2 bit được XOR khác nhau).

TEST DST , SRC: So sánh nội dung 2 toán hạng qua phép toán AND. Kết quả tác động đến các cờ.

SHL DST, CL: Dịch trái các bit toán hạng đích Count lần (Count = CL). Ý nghĩa tương đương DST = DST * 2^CL.

SHR DST, CL: Tương tự là dịch phải và là phép chia 2^CL
* Cách dịch bit bằng cách đưa bit bị dịch vào CF thay bit dồn lên là bit 0.

SAL / SAR: tương tự 2 chỉ lệnh trên nhưng dành cho các số có dấu.

ROL / ROR: Dịch bit nhưng bit bị dịch được bảo tồn bằng cách chuyển về đầu bên kia phép dịch.

RCL / RCR: Tương tự nhưng giá trị cở CF là giá trị sẽ được dùng để dồn vào đầu bên kia phép dịch.

Jump Codition

JA Jump If Above
JAE Jump If Above or Equal
JB Jump If Below
JBE Jump If Below or Equal
JC Jump If Carry
JCXZ Jump if CX Register Zero
JE Jump If Equal
JG Jump If Greater
JGE Jump If Greater or Equal
JL Jump If Less
JLE Jump If Less or Equal
JMP Jump Unconditionally
JNA Jump If Not Above
JNAE Jump If Not Above or Equal
JNB Jump If Not Below
JNBE Jump If Not Below or Equal
JNC Jump If No Carry
JNE Jump If Not Equal
JNG Jump If Not Greater
JNGE Jump If Not Greater or Equal
JNL Jump If Not Less
JNLE Jump If Not Less or Equal
JNO Jump If No Overflow
JNP Jump If No Parity
JNS Jump If No Sign
JNZ Jump If Not Zero
JO Jump If Overflow
JP Jump If Parity
JPE Jump If Parity Even
JPO Jump If Parity Odd
JS Jump If Sign
JZ Jump If Zero


Mời các bạn đón phần tiếp
RefLink: http://www.diendantinhoc.vn/archive/index.php?t-4978.html

[Reverse] Let’s Cracking by Olly

Let’s Cracking by Olly

BÀI 2: LET’S PATCH THE SOFTS BY OLLDBG

Ok, bây giờ chúng ta hảy bắt đầu làm quen với các chức năng của Oll nhé
Softs ở đây tui chọn cái Patchme No.1 mới ra lò của bác QHQCrcker .Các bạn download ở đây:
Link:
http://www.reaonline.net/forum/showthread.php?t=163

I.Thu thập thông tin về chương trình cần crack:
Chúng ta hảy chạy cái crackme.exe xem sau:
-Nó bắn ra 1 cái Nag chào hỏi theo kiểu Tây: Hi
Hello Newbiez wold.....
Và thước yêu cầu:
Rulez :
1. Patch nag (Bỏ cái Nag này)
2. Change bad text to GOODBOY text. (Thay đổi cái text trong Nag sau thành GOODBOY text)
3. Enable Exit button. (Cho nút button Exit có tác dụng)
- Bấm Ok nó sẽ hiện cái Nag thứ 2: QHQ Patch me No.1
- Exit chương trình, bây giờ Patch nó thôi
II Thực hành Pacth soft :

Các bạn mở chương trình Oll, vào Menu File/Open : Load chương trình QHQPatchmeNo1.exe vào Oll(Hay bấm F3 cũng được)

Chức năng đầu tiên tui muốn giới thiệu với các bạn là:

1.Run (F9) : Chạy chương trình trong Oll.

Bấm F9 chạy thử chương trình trong Oll xem sau.
Các bạn thấy sau, nó bắn Nag đầu tiên phải ko?.Bấm button OK chương trình bị crash chứ gì?. Đây cũng là 1 cách bảo vệ chương trình ko có các Cracker phá phách .Nguyên tắc của nó là khi phát hiện máy tính của bạn đang chạy chương trình debugger thì sẽ crash phá vỡ cấu trúc code của chương trình ko cho chạy tiếp , cơ chế này các cracker hay gọi là Anti-debugger gì đó...Hìhì
Vậy chúng ta pó tay sao??
Bình tỉnh nhé, chúng ta Load lại chương trình trong Oll xem sau.
Tui muốn ghi chú các bạn ở đây 1 chút : Oll chạy qua 1 chương trình thì coi như một đi ko trở lại. Nó chỉ để lại những “dấu chân trên cát” mà thôi. Tức là nó sẽ báo ta nhưng gì nó đã đi qua chứ ko quay lại được.Muốn làm việc lại với nó ,chúng ta phải Load nó lại vào Oll .
OK, bây giờ tui sẽ giới thiệu các bạn chức năng Load lại chương trình một cách nhanh chóng mà ko cần phải bấm F3 rồi chọn lại file cho rắc rối.Đó là:

2.CTRL+F2 : Đây là chức năng chạy lại chương trình.

Hihi , các bạn thấy ko , tòan là các phím nóng. Làm sao mà nhớ hết đây trời!. Không sao, không sao, làm nhiều sẽ tự động nhớ thôi. Hy vọng thế!!!!!!
Sau khi Load lại chương trình, tui có ý tưởng như sau:
Vì tui biết chương trình patchme ko bị crash ở cái Nag đầu tiên nên sau ta ko tạm ngưng chương trình khi nó bắn cái Nag đầu tiên. Rồi vào cửa số code xem code nó ở đâu để patch cái Nag đó theo yêu cầu của tác giả.Vậy chúng ta phải tìm hiểu chức năng kế tiếp là :

3. Pause ̣F12 : Tạm ngưng chương trình.

OK, bây giờ các bạn bấm F9, chạy chương trình.Khi bắn cái Nag đầu tiên các bạn khoan hả bấm nút OK mà hảy trờ lại Oll bằng cách click vào cửa sổ Oll. Sau đó bấm F12. Các bạn hảy nhìn cửa sổ code cửa window CPU xem sao. Tòan là mã code trong bộ nhớ , ko phải là mã code chương trình. Vậy là phá sản sao?
Tui nghĩ lại có ý kiến thử cho chương trình tự động trace over (trace ko vào hàm Call để soi mói) từng dòng lệnh 1 cách chầm chậm khi muốn ngừng ở đâu thì ta pause ở đó để xem đọan code nó là gì. Mục đích ở đây là trong cái cửa sổ code của window CPU có đọan code của chương trình
Ehèm, và thật sự Oll đã có chức năng này. Tui xin giới thiệu các bạn

4.Animate Over (CTRL+F8):

Chức năng này như sau: Trace từng dòng lệnh mà ko vào hàm call ‘soi mói’ (trace over) một cách “chậm chậm “ và trong cửa sổ code của CPU hiện ra quá trình khi trace.Chức năng này tui gọi tóm tắc là TraceO động
Tui hay sử dụng chức năng để đi dến các đọan code bắn Nag đó các bạn.
OK, bây giờ thử xem sau:
-Load lại chương trình CTRL+F2
-Bấm CTRL+F8 : traceO động. Nó bắn ra Nag đúng ko
-Bây giờ trở lại Oll, đừng bấm F12 nhé. Ta thấy Oll ngừng tại đọan code sau để chờ ta bấm phím OK(chúng ta lợi dụng chức năng này để tìm ra Nag):

Quote:

00401021 > 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
00401023 68 EB304000 PUSH QHQPatch.004030EB ; |Title = "Hi"
00401028 68 56304000 PUSH QHQPatch.00403056 ; |Text = "Hello newbiez world. Try with me! Rulez : 1. Patch this nag.2. Patch the BADBOY static 3* Make Exit button is Visible. Hope you fun with me..."
0040102D 6A 00 PUSH 0 ; |hOwner = NULL
0040102F E8 2E050000 CALL ; \MessageBoxA <<<<<<<00401034 |. E8 0B050000 CALL ; [IsDebuggerPresent
00401039 |. 0BC0 OR EAX,EAX
0040103B |. 74 07 JE SHORT QHQPatch.00401044
0040103D >|. C605 01304000>MOV BYTE PTR DS:[403001],1

OK rồi nhé chúng ta đã tìm ra đọan code bắn Nag.
Bây giờ tui sẽ chỉ bạn cách đánh dấu mã code này , để mỗi lần ta load lại chương trình muốn goto đến đọan code này thì sẽ rất dễ dàng . Chúng ta ko cần phải viết ra giấy addr cần nhớ như SI nữa.

5.Label : Đánh dấu dòng lệnh hay “gắn 1 cái nhãn” cho dòng lệnh nào đó.

Bây giờ các bạn đang đứng tại đọan code bắn Nag trong Oll, nhắc lại đừng bấm F12 nhé. Các bạn hảy nhìn bên dưới màn hình Oll , góc tay phải hiển thị chế độ làm việc như sau: Animating đúng ko các bạn . Nếu đúng thế thì máy của bạn đang ở trạng thái như máy của tui. Các bạn hảy nhìn chổ này cho quen mắt nhé đây là nơi chúng ta biết thằng Oll đang làm gì.
Tiếp theo các bạn click vào dòng dưới lệnh này:
00401034 |. E8 0B050000 CALL ; [IsDebuggerPresent

Sau đó click phải vào nó, sẽ hiển thị 1 menu pop-up. Chọn Label. Đánh vào 1 cái tên nào đó cho dòng lệnh này.Ở đây tui đánh name: “point1”. Bấm Ok. Vậy là chúng ta đã đặt tên cho dòng lệnh trên là ‘point1’
OK, bây giờ các bạn bấm CTRL+F2 load lại chương trình.
Đừng chạy chương trình, các bạn hảy click phải trong cửa sổ CPU, chọn Goto/Expression ( hay nhấn CTRL+G). Đánh vào name: ‘point1’. Con trỏ cửa cửa sổ CPU sẽ nhảy đến dòng lệnh mà ta đặt tên.
Bây giờ tui sẽ chỉ các bạn cách NOP các dòng lệnh sau để patch cái Nag đầu tiên:

Quote:

00401021 > 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
00401023 68 EB304000 PUSH QHQPatch.004030EB ; |Title = "Hi"
00401028 68 56304000 PUSH QHQPatch.00403056 ; |Text = "Hello newbiez world. Try with me! Rulez : 1. Patch this nag.2. Patch the BADBOY static 3* Make Exit button is Visible. Hope you fun with me..."
0040102D 6A 00 PUSH 0 ; |hOwner = NULL
0040102F E8 2E050000 CALL ; \MessageBoxA

Vì sau chúng ta NOP các dòng này thì sẽ patch cái Nag đầu tiên , xin các bạn đọc tut “Một cách Kill Nag dùng hàm MessageBoxA” mà tui đã viết.
Đầu tiên chúng ta click chọn dòng lệnh đầu tiên , bấm và giử nút Shift sau đó click vào dòng lệnh cuối cùng, Tòan bộ nhóm lệnh trên được chọn .
Bây giờ chúng ta click phải vào nhóm lệnh đã chọn >> menu pop-up/Binary/ Fill with NOPs.
Sau khi chọn như trên thì Oll sẽ NOP tòan bộ nhóm lệnh trên. (Rất nhẹ nhàng so với sử dụng HIEW).Các bạn hảy nhìn vào cửa sổ Code sẽ thấy được điều đó.
Ở đây chúng ta chỉ NOP chương trình đang Load trong bộ nhớ chứ ko phải trên File chúng ta đang crack. Vậy nhiệm vụ kế tiếp là chúng ta phải “bức” cái chương trình đang nằm trong bộ nhớ lưu ra thành 1 file mới , việc này các cracker hay gọi là “dump” nó ra đó bạn.
Chú ý:
-Muốn làm được điều này bạn phải có Plugin OllDump , tức là cái Oll của bạn trên thanh menu có mục Plugin/OllDump.
-Qui tắc Dump khi patch: Chương trình mới Load (CTRL+F2), tức là chưa trace hay run qua 1 dòng lệnh nào,kế đó là patch những dòng lệnh cần thiết, sau đó Dump lưu ra file.(tui sẽ giải thích sau)
Bây giờ thực hành nhé: Các bạn chọn menu Plugin/OllDump/Dump Debugged Process.
Đừng thay đổi gì hết, bấm OK, đánh vào tên file lưu ra đĩa. Bấm OK.
Bây giờ bạn kiểm tra lại file đã dump có chạy ko nhé.
Tut này dài quá rồi, Hen tut sau tui sẽ giới thệiu các bạn nhiều chức năng hấp dẫn của OllDbg. Chúc các bạn thành công

BÀI 3: W32DASM+HIEW+SI=OLLDBG??

Tính gác kiếm về quê cưới vợ , hôm qua vào mạng rao bán đấu giá cái nick benina để có tiền về xe. Nhưng chẳng thấy ma nào mua. Đành ở lại Sì gòn nghiêu ngao vài ba chuyến rồi tính sao. Cái gì nó đến chắc cũng sẽ đến. AQ của Lỗ Tấn là bạn của tui mà , nó dạy tui như thế : ))
Hôm nay nghiêu ngao lên mạng, các bạn nữ nhi chi chi (BD hay “lai cái” gì cũng được) “đòi hỏi” quá ,nên để chiều lòng các “người đẹp”, tui lại bắt đầu viết Tut tiếp cho newbiez. Hihi. Đây cũng là TUT minh họa cho lọat TUTS của anh RongChauA. Và mục đích của lọat TUT này ko còn là hướng dẫn sử dụng về Olly nữa. Mà là vận dụng các tính năng của Olly để cracking. Hy vọng tut này ko làm cho các bạn thất vọng.Trước khi đọc TUT này các bạn hảy tìm đọc các TUT useOlly của RongChauA nhé.
Vào đề sớm:
Trong forum HVAonline.net có 1 bạn (hình như là mailhn thì phải) hỏi crack phần mềm Ripple Screensaver 3.0. Tui tải phần mềm này về lâu lắm rồi nhưng ko có thời gian để xem. Hôm nay tìm 1 soft cho Newbie nên đem ra thì thấy cũng hay hay nên viết tut này cho các bạn . Các bạn đừng tưởng đây là phần mềm củ xì vào thập niên 90 nhe, nó đang rao bán trong năm 2004 đấy. Nên hơn khó một chút. Vì trình độ chúng ta bắt đầu nâng cao thêm một tí nên tui sẽ chỉ các bạn cách tìm Real Searial (tìm số đăng ký đúng) nhé.

Ripple ScreenSaver v3.0 ở :
hxxp://www.wcgame.com/ripple-screensaver/index.html

Công cụ ở đây dùng cái gì cũng được SI + W32Dasm hay Olly đều được cả. SI có ưu điểm là tìm điểm mở đầu đọan tạo searial rất nhanh (tui thích SI điểm này) , còn W32Dasm thì tìm điểm kết của đọan tạo searial . Một cái là “nắm đầu” , còn 1 cái là “bóp đí..t” ( nói bậy bỏ qua nhe nhưng ví dụ như vậy thì học rất dễ vô hê hê). Đặc biệt thì Olly “nắm đầu” hay “bóp đí..t” đều được cả. Anh chàng này tương đối đa năng. Nên các cracker rất thích dùng. Để ko tuộc hậu , chúng ta phải học Olly thôi .
Bây giờ tui sẽ chỉ cho các bạn tiếp các sử dụng Olly (các bạn tham khảo thêm càc bài của anh RongChauA), nhưng trước hết các bạn cài phần mềm Ripple Screensaver 3.0 vào máy.

VẬN DỤNG OLLY ĐỂ CRACK: (phần tiếp theo)
Như các bạn đã biết, tui chỉ nhắc lại, đầu tiên các bạn chạy chương trình để thu thập thông tin . Chương trình này chỉ cho dùng thử trong 30 ngày. Nếu quá 30 ngày thì nó bắt ta mua giá hữu nghị là 14.95$ . Nhưng hôm nay tui hữu nghị hơn tác giả phần mềm, sẽ tặng ko cho bạn mà ko cần đồng nào , chỉ cần vài giọt mồ hôi của bạn mà thôi hìhì.
Bây giờ chúng ta hãy đổi năm trên máy bạn thành năm 2005 xem sao (hiện tại là năm 2004 đúng ko?). Khi các bạn click vào biểu tượng của nó trên desktop thì như Chị Dậu của Nam Cao thấy tương lai “tối đen như mực”, màn hình đen thui và hiện lên dòng thông báo đỏ: “This is a trial version of Ripple Screensaver. You have alrealdy eceeded the trial period. If you love Ripple Screensaver, please purchase it. Thank you”
(Thật là buồn cười khi phải “purchase it”. Người VN ko có thóai wen này thì phải.)
Sau đó , khi bạn di động con chuột thì nó hiện hộp thọai yêu cầu nhập License Name và License Code.
Bạn hảy nhập bậy bạ vào xem sao
License Name: benina
License Code: 0123456789
Nó sẽ bắn nag: “Rigistration failed! ......”
Ok, thóat ra đi bạn và tải file C:\window\ RSRemider.exe vào Olly.
Như các bạn đều biết , cách crack truyền thống là tìm xem “đít” của đọan mã tạo searial dựa vào đọan string “Rigistration failed! ......” nằm đâu rồi “mò lên” để tìm “tử huyệt” của chương trình. Cách tìm đọan string trong W32Dasm thì các bạn đã biết còn trong Olly thì làm như sau:
7. Search string:
Khi các bạn open 1 file thì trên Olly cửa sổ CPU sẽ hiện ra . Nếu ko thấy thì Click vào button trên thanh menu có ký hiệu là ký tự “C” tui gọi là Button “C”. Các bạn click phải vào cửa sổ Code của CPU window, một menu popup hiện ra, vào Search for/All referenced text string.
Khi ấy cửa sổ “Text string referenced “ sẽ hiện ra . Bạn hảy tìm xem có đọan string “Rigistration failed! ......” đang nằm đâu. Bạn thấy nó chưa? (Có phải tại address : 00401239 không nào!). Hảy DClick và address của nó . Khi đó Olly sẽ trỏ đến địa chỉ của nó trong cửa sổ Code của CPU window.

Quote:

00402232 > \6A 10 PUSH 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00402234 . 68 CC424000 PUSH RSRemind.004042CC ; |Title = "Ripple Screensaver"
00402239 . 68 64434000 PUSH RSRemind.00404364 ; |Text = "Registration failed! You entered a invalid license code.
Please make sure there is no typing mistake and you have installed the newest product.
Then try again!" <<<<<<<<<đang ở đây
0040223E . 56 PUSH ESI ; |hOwner
0040223F . FF15 08324000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA

OK, vậy là xong 1 chức năng của Olly . Phù Phù , mệt thiệt. Tiếp tục nhe:

Chức năng kế tiếp tui muốn giới thiệu các bạn đó là cách đặt breakpoint lọai Toggle (chốt tiến trình lại) . Nó giống như lệnh đặt bp One-shot ( F7 )trong SI.
8. Toggle F2 (Breakpoint Toggle)
Bây giờ bạn hãy “mò lên” trên trong Code window một chút, và ta nghi ngờ “tử huyệt“ nằm ở lệnh nhảy này:

Quote:

00402204 > \50 PUSH EAX
00402205 . B9 20454000 MOV ECX,RSRemind.00404520
0040220A . E8 87010000 CALL RSRemind.00402396
0040220F . 8B46 64 MOV EAX,DWORD PTR DS:[ESI+64]
00402212 . B9 20454000 MOV ECX,RSRemind.00404520
00402217 . 50 PUSH EAX
00402218 . E8 95010000 CALL RSRemind.004023B2
0040221D . B9 20454000 MOV ECX,RSRemind.00404520
00402222 . E8 05030000 CALL RSRemind.0040252C
00402227 . 85C0 TEST EAX,EAX
00402229 75 2A JNZ SHORT RSRemind.00402255 <<<<<<< Tử huyệt ????
0040222B . 85F6 TEST ESI,ESI
0040222D . 74 03 JE SHORT RSRemind.00402232

Bạn hảy click vào dòng lệnh nghi ngờ đó xem sau. Olly sẽ xuất hiện 1 mũi tên chỉ nó nhảy từ địa chỉ trên đến đọan mã sau:

Quote:

----------------------------------------------------------
(Từ địa chỉ này bắt đầu nhảy .....
00402229 75 2A JNZ SHORT RSRemind.00402255 <<<<<<< Tử huyệt ????
......
......

......
......
(Nhảy đến đây)
00402255 > \8D4C24 04 LEA ECX,DWORD PTR SS:[ESP+4]
00402259 . E8 98050000 CALL
0040225E . 8B46 60 MOV EAX,DWORD PTR DS:[ESI+60]
00402261 . 8D4C24 04 LEA ECX,DWORD PTR SS:[ESP+4]
00402265 . 50 PUSH EAX
00402266 . 68 1C434000 PUSH RSRemind.0040431C ; ASCII "Congratulations! This product is licensed to:
Enjoy it now!"
0040226B . 51 PUSH ECX
0040226C . C74424 1C 000>MOV DWORD PTR SS:[ESP+1C],0
00402274 . E8 BF050000 CALL
---------------------------------------------------------------------------

Rất ấn tượng phải ko các bạn. Tôi yêu Olly ở chổ này (hihi).
Đến đây các bạn thấy gì ko. Tui thấy dòng này:
"Congratulations! This product is licensed to:
Enjoy it now!"
OK, vậy là tử huyệt rồi???.
Vậy chúng ta hảy patch thử nó trong Olly xem sau.Muốn vậy chúng ta thử đặt bp tại đó xem nhé. Đây là cách đặt bp Toggle :
Để chương trình ngừng (break) lại tại địa chỉ nào khi Run ,chúng ta click chuột vào địa chỉ đó và nhấn F2 , khi ấy tại địa chỉ đó nó sẽ đổi màu khác.

Đơn giản như đang giởn phải ko các bạn.
Bây giờ các bạn hảy Toggle tại địa chỉ “tử huyệt” đi. Và ấn F9 cho chương trình chạy , nhập Name và Fake Code xem sao. Nó có ice tại đó ko?. Đừng nói là ko nhe.

Vậy là xong 1 chức năng nữa. Bây giờ tui sẽ chỉ các bạn cách Patch thử trong Olly.

9. Edit Binary(CTRL+E)
Như trên tui đã nói , chúng ta hảy patch thử dòng lệnh trên xem sao. Các bạn đã biết cách patch trong HIEW rồi. Ở đây chức năng này cũng tương tự , nhưng khác ở chổ nó patch chương trình nằm trong bộ nhớ thôi , chứ ko phải trên file trong đĩa cứng. Nhớ nhé. Vì vậy tui mới gọi đây là các “patch thử “.
Như các bạn biết:
JNZ có mã là 75
JZ có mã là 74
Chúng ta hảy thay lệnh JNZ này thành JZ bằng cách thay mã 75 thành 74. Chúng ta làm như sau:
Click vào dòng lệnh JNZ :

00402229 75 2A JNZ SHORT RSRemind.00402255 <<<<<<< Tử huyệt ????

Bấm CTRL+E sẽ hiện ra hộp thọai “Edit Code”, các bạn hảy thay 75 thành 74 và bấm OK. Sau đó bấm F9 chạy tiếp xem sau. WOW nó hiện ra hộp thọai sau:
"Congratulations! This product is licensed to:
benina
Enjoy it now!"
Bấm OK, vậy là đăng ký xong.
Vậy là chúng ta đã patch xong chương trình này rồi ư. Quá dễ ?????.
Để biết chắc ăn chúng ta hảy thóat Olly , và chạy chương trình xem sao.
OOOOH !!!
Nó lại đòi đăng ký và vẫn còn thông báo “ . Vậy là ko xong rồi. Nó khó hơn những gì ta tưởng các bạn ạ. Vì vậy chúng ta buộc lòng phải vào xem hàm tạo searial ra sao để tìm Real searial cho chương trình.
Nhưng trước khi bước vào lĩnh vực Real Searial tui xin hướng dẫn các bạn một chức năng nữa của Olly để patch tạm .Tính năng này giống như lệnh “a” trong SI. Đó là chức năng Assemble (phím Space)

10.Assemble (phím Space) hay menu popup of Code window\Assemble

Bây giờ mở lại chương trình Olly. Nhấn Ctrl+F2 load chương trình lên. Bấm ALT+B để mở Breakpoint window xem bp ta đặt trước đó có còn ko. Bạn thấy còn chứ. Vậy là Olly đã nhớ những gì ta làm trong phiên làm việc trước. Thật là tiện lợi phải ko các bạn. Chúng ta sẽ ko cần phải đặt bp như từ đầu. Chúng ta nhấn F9 để run. Và làm tương tự như trên cho đến khi thay vì patch bằng Edit Binary(CTRL+E) thì chúng ta patch bằng chức năng Assemble. Các bạn làm như sau:


Click vào dòng lệnh JNZ :

00402229 75 2A JNZ SHORT RSRemind.00402255 <<<<<<< Tử huyệt ????

Bấm Phím Space sẽ hiện ra hộp thọai “Assemble”, các bạn hảy thay :
JNZ SHORT 00402255
Thành
JZ SHORT 00402255 (Xóa bớt chử N của lệnh JNZ)

và bấm button “Assemble”. Các bạn sẽ thấy trong cửa sổ code của CPU Window tại dòng lệnh trên sẽ thay bằng lệnh:

00402229 74 2A JE SHORT RSRemind.00402255

Sau đó đóng hộp thọai “Assemble” và bấm F9 chạy tiếp xem sau. Bắn ra Nag good phải ko các bạn.Nhưng vẫn chưa crack xong ,Oki?. Đến đây thì các bạn đã biết patch bằng chức năng Assemble rồi đấy.

Đến đây thì chúng ta thấy anh chàng Olly này có tuyệt vời không các bạn. Nó có chức năng Search String giống W32Dasm, chức năng Edit Binary giống HIEW, chức năng “Assemble” giống SI. Đúng là một phần mềm “đa chủng tộc”.
Vì vậy các proprammer và các cracker xúm nhau hổ trợ cho Olly rất nhiều. Họ viết các Plugins cho Olly thêm phần phong phú. Các Plugins này bổ túc thêm các tính năng mà Olly không có. Phần tiếp theo đây tui sẽ giới thiệu các bạn 1 Plugins đơn giản của Olly.
Thưa các bạn , Benina viết tut ko theo một lề lối nào hết. Đụng đến đâu viết đến đó, đây là phong cách “mì ăn liền” rất tệ hại theo quan điểm các nhà mô phạm. Vì vậy tui rất khâm phục anh RongChauA đã viết các TUT UseOlly (các tut này , anh RongChauA làm đẹp cực kỳ bằng file .pdf). Các tut của anh rất mô phạm và hấp dẫn . Các bạn hảy download về mau mau kẻo đứt Link down thì khổ. Nhưng như trên tui giới thiệu, đây chỉ là lọat tut thực hành về Olly (như một bạn nào đó yêu cầu tui viết tut như vậy), nên chúng ta thấy “mì” thì “ăn liền”, đụng đến đâu xơi đến đó...hihi. Nhưng xơi nhiều quá coi chừng “bội thực” . Chúng ta xơi từ từ thôi. Mỗi lần một tính năng của Olly là được rồi.
Bây giờ trở lại với Olly, tui xin giới thiệu với các bạn một Plugins đơn giản nhất của Olly :

11.Pluggins\CleanupEx

Ở đây tui ko nhắc lại cách cài Plugins cho Olly, vì như vậy thì TUT quá dài dòng. Phần này các bạn hãy chờ anh RongChauA hướng dẫn. Còn nếu ko chờ được thì các bạn hảy post 1 mục trong forum này hỏi cách cài Plugins như thế nào để nhờ mọi người hổ trợ. Các bạn mà ko biết hỏi thì ko bao giờ giỏi được đâu. Hảy nhớ lấy câu này các bạn ạ.
Trở lại vấn đề, như ở trên tui đã nói , khi vào lại Olly thì những gì ta làm trong phiên làm việc trước ,Olly sẽ lưu lại giùm ta (như đặt bp Toggle chẳng hạn). Đây là một tính năng rất hay của Olly, gíup ta ko phải làm lại những công việc nhàm chán trong phiên làm việc trước. Nhưng nó cũng là con dao 2 lưỡi cho các Newbie. Vì Newbie thì chưa biết nhiều về Olly , nên vọc từa lưa khi crack , mà Olly thì lại máy móc lưu hết những gì họ đã làm. Thành thử ra, khi vào crack trong phiên làm việc sau rất khó chịu với anh chàng Olly mà mình lỡ vọc từa lưa. Muốn xóa sạch “dấu vết” mà mình lỡ “khờ dại” làm ra ,các bạn hảy dùng tính năng CleanupEx. Vì vậy tui mới giới thiệu tính năng này sớm cho các bạn.
Ehèm, muốn xóa sạch “dấu vết” trong phiên làm việc trước, các bạn vào menu Plugins trên thanh Tools Bar, chọn CleanupEx\Last Used. Còn nếu muốn xóa hết tất cả các “thiên tình sử” mà mình “lỡ dại” khi crack các phần mềm trước đó , các bạn chọn CleanupEx\All(*.udd*bak) là xong . Bây giờ thì các bạn muốn “yêu” lại em nào thì yêu thỏai mái , mà ko sợ những “tội lỗi” lúc trước mình gây ra....hêhê (đã nạo sạch...híhí). Ước gì ngòai đời có chức năng này, vì tui gây ra rất nhiều “tội lỗi”. Lạy Chúa con hối hận lém.


Đến đây nếu các bạn nào nóng ruột không muốn tìm hiểu tiếp hay không hiểu những gì tui post và ko cần đọc tiếp các phần sau mà muốn sử dụng phần mềm này ngay thì các bạn hảy nhập số searial như sau:

Quote:

License Name: Single License
License Code: ZZZZZZZZZPPPPPQ


Còn nếu các bạn nào kiên trì muốn tìm hiểu tiếp các phần sau (vì tut này tui dự trù viết rất dài nhằm để các Newbiez hiểu tường tận đọan mã tạo Serial) thì các bạn ko nên nhập số searial tui đã cho vì còn phải làm việc với cái chương trình này .
Tại sao Tut này tui dự trù viết dài như thế ??. Thưa các bạn vì đến đây để vượt qua được ngưỡng cửa Newbie thì chúng ta phải tìm hiểu về các đọan code ASM. Và đây lại là Tut đầu tiên của Newbie tìm hiểu về code ASM nên rất nhiều các khái niệm căn bản phải giải thích. Nhưng các newbie an tâm, nhiều khi các cracker lọai trung cũng chưa chắc nắm rõ ràng những điều căn bản này (nói thiệt tui post chứ nhiều khi tui ko hiểu gì ráo, tui post ở đây giống như nói xàm cho vui). Các bạn cứ học từ từ theo Benina thì đến ngày nào đó chúng ta sẽ hôi “cái mùi cracker” nòng nặc thôi. Lúc đó tắm xà bông Lux cũng chưa chắc thơm nổi như Mỹ Tâm.

Các bạn hảy chờ Tut sau nhé.Bài này thực ra là một ví dụ về tính đa năng của Olly. Nó giống như một bài báo bình thường ko có gì đặc biệt. Hy vọng các bạn nào chưa biết các tính năng này sẽ hài lòng với TUT này.
Mệt quá rồi cho Benina nghĩ xả hơi 1 chút. Mấy hôm nay mới đi qua Hà Lan mua sữa của mấy “cô gái Hà Lan” về uống , nên đến giờ ghiền rồi phải đi bú thôi ....ai muốn, tui chia lại cho vài lít.....híhí

BÀI 4: FIND REAL SEARIAL
PHẦN I: KHÚC DẠO ĐẦU VỚI “FIND REAL SEARIAL”

Chắc các bạn cũng đã từng đọc qua lọat TUT “Craker!WhoAreYou” của Hacnho để tìm Real Searial, hay loạt tut “How To Crack” của Infinite đầy tài năng, cũng như lọat tut “CrackSoft’s Tuts” và “Crackme for Newbie”của Moonbaby chuyên gia crack softs ,hoặc ”How to use OllDbg” của RongChauA đã viết rất lâu, các bạn có hiểu gì ko nào?. Nếu các bạn đã hiểu những lọat Tut tui kể trên thì các bạn ko phải là đối tượng cho lọat TUT này. Ở đây Benina chỉ muốn chia sẽ với các bạn còn đang khó khăn khi chưa hiểu những gì viết trong các lọat TUT trên. Cái quan trọng là các bạn Newbie chưa biết đọc mã ASM . Khi ko biết đọc thì ko thể biết viết được ( Ở đây tui muốn nói đọc và hiều).Benina sẽ cùng học với các bạn đọc và hiểu các đọan mã ASM qua lọat tut này,như vậy là đã đủ cho 1 cracker Newbie rồi. Còn để viết được một chương trình ASM , hêhê ...chuyện dài hơi.
Như trên tui đã nói, các bạn Newbie rất khó khăn khi đọc các lọat TUT trên. Không phải vì các tác giả viết dỡ , nhưng vì chúng ta mất “cãn bản” trầm trọng . Không hiểu được mã ASM. Vì vậy Benina sẽ cố gắng hết sức mình, trình bày thật dễ hiểu cho các bạn Newbie như benina đây. Thành thử khi các bạn ko hiểu những gì benina viết thì please báo với benina để điều chỉnh cách viết ngay. Đồng thời như thế benina cũng học hỏi rất nhiều ở các bạn.
Trong lọat TUT này , vì trình độ của các bạn cũng có phần nâng cao so với “thuở ban đầu lưu luyến ấy” , và cũng để cho nó thêm phần hấp dẫn, Benina sẽ chọn các softs “mới cáo” làm ví dụ. Và một quy tắc nữa của benina là trong quá trình hướng dẫn , benina sẽ cố tình post một vài điểm sai, nếu các bạn làm “y chang” với những gì benina posted thì sẽ ko crack được đâu. (hihi). Cái này ko phải là “giấu nghề” (có nghề đâu mà giấu) mà là tránh phiền phức về sau. Mong các bạn thông cảm. Đó là quy tắc “nhát như thỏ” của benina. Benina chưa bao giờ phạm pháp ...chỉ dịch TUT thôi mà...hêhê. Tóm lại, mục đích cuối cùng của lọat TUT này chỉ là giúp các bạn thực hành Olly và đọc hiểu mã ASM có thế thôi.
Các bạn thấy đó, trong các tut trên , các cracker chỉ comment vắn tắc như sau mà một Newbie thì ko thể nào hiểu được:
Ví dụ:

Quote:

Target: Ripple Screensaver 3.0
Dùng phương pháp search string của “bad boy” ta đến đọan mã sau đây và đặt bp như sau:

Quote:

00402204 > \50 PUSH EAX
00402205 . B9 20454000 MOV ECX,RSRemind.00404520
0040220A . E8 87010000 CALL RSRemind.00402396
0040220F . 8B46 64 MOV EAX,DWORD PTR DS:[ESI+64]
00402212 . B9 20454000 MOV ECX,RSRemind.00404520
00402217 . 50 PUSH EAX
00402218 . E8 95010000 CALL RSRemind.004023B2
0040221D . B9 20454000 MOV ECX,RSRemind.00404520
00402222 . E8 05030000 CALL RSRemind.0040252C<<<<<<<< đặt bp Toggle
00402227 . 85C0 TEST EAX,EAX
00402229 75 2A JNZ SHORT RSRemind.00402255
0040222B . 85F6 TEST ESI,ESI
0040222D . 74 03 JE SHORT RSRemind.00402232
0040222F . 8B76 20 MOV ESI,DWORD PTR DS:[ESI+20]

Press F9, Nhập Fake Name: benina và Fake Code: 0123456789. Rồi press F7 step into vào hàm :
========================
0040252C /$ 55 PUSH EBP ; Thủ tục đầu tiên của hàm call
0040252D |. 8BEC MOV EBP,ESP
0040252F |. 81EC 0C010000 SUB ESP,10C
00402535 |. 53 PUSH EBX
00402536 |. 56 PUSH ESI
00402537 |. 8BD9 MOV EBX,ECX
00402539 |. 33F6 XOR ESI,ESI ; esi=0
0040253B |. 3973 04 CMP DWORD PTR DS:[EBX+4],ESI
0040253E 74 08 JE SHORT RSRemind.00402548
00402540 |. 6A 01 PUSH 1
00402542 |. 58 POP EAX
00402543 |. E9 DB000000 JMP RSRemind.00402623
00402548 |> 80A5 F4FEFFFF>AND BYTE PTR SS:[EBP-10C],0
0040254F |. 57 PUSH EDI
00402550 |. 6A 40 PUSH 40
00402552 |. 33C0 XOR EAX,EAX ; eax=0
00402554 |. 59 POP ECX
00402555 |. 8DBD F5FEFFFF LEA EDI,DWORD PTR SS:[EBP-10B]
0040255B |. F3:AB REP STOS DWORD PTR ES:[EDI]
0040255D |. 3973 0C CMP DWORD PTR DS:[EBX+C],ESI ; Tham so [ebx+c]=esi=0 ?
00402560 |. 8975 FC MOV [LOCAL.1],ESI ;Biến Local local.1=0=esi
00402563 |. 66:AB STOS WORD PTR ES:[EDI]
00402565 |. 8975 F8 MOV [LOCAL.2],ESI ;Biến local.2=0
00402568 |. AA STOS BYTE PTR ES:[EDI]
00402569 74 07 JE SHORT RSRemind.00402572 ; Nhay ko dùng Fake Name de tinh toan
0040256B |. 68 34444000 PUSH RSRemind.00404434 ; ASCII "Single License"
00402570 |. EB 07 JMP SHORT RSRemind.00402579
00402572 |> 8D83 14010000 LEA EAX,DWORD PTR DS:[EBX+114] ; [ebx+114]=Fake name='benina'
00402578 |. 50 PUSH EAX
00402579 |> 8D85 F4FEFFFF LEA EAX,[LOCAL.67] ; |
0040257F |. 50 PUSH EAX ; |dest
00402580 |. E8 69040000 CALL ; \eax='Single License' Name default
00402585 |. 59 POP ECX ; 'Single License'
00402586 |. 8D85 F4FEFFFF LEA EAX,[LOCAL.67] ; 'Single License'
0040258C |. 59 POP ECX
0040258D |. 33FF XOR EDI,EDI ; edi=0 ===> khoi tao counter i=0
0040258F |. 50 PUSH EAX ; /eax=Name default = 'Single License'
00402590 |. E8 5F040000 CALL ; \strlen
00402595 |. 85C0 TEST EAX,EAX ; eax=0E ===> chieu dai Name df=15 ky tu
00402597 |. 59 POP ECX ; ecx= Name default : 'Single License'
00402598 |. 7E 1D JLE SHORT RSRemind.004025B7
0040259A |> 0FBE843D F4FE>/MOVSX EAX,BYTE PTR SS:[EBP+EDI-10C] ; eax=Ky tu thu [i] cua chuoi Name
004025A2 |. 0145 FC |ADD [LOCAL.1],EAX ; Bien Local.1=Local.1+eax
004025A5 |. 8D85 F4FEFFFF |LEA EAX,[LOCAL.67] ; eax=[Local.67]= chieu dai Name df
004025AB |. 50 |PUSH EAX ; /Name
004025AC |. 47 |INC EDI ; |edi=edi+1 ===>Counter i=i+1
004025AD |. E8 42040000 |CALL ; \strlen
004025B2 |. 3BF8 |CMP EDI,EAX ; edi=eax ?
004025B4 |. 59 |POP ECX
004025B5 |.^ 7C E3 \JL SHORT RSRemind.0040259A ; cuoi vong lap local.1=545 (dump: d loacal.1)
004025B7 |> 8DB3 18020000 LEA ESI,DWORD PTR DS:[EBX+218] ; esi= code '0123456789'
004025BD |. 33FF XOR EDI,EDI ; edi=0 ===>counter i=0
004025BF |. 56 PUSH ESI ; /s
004025C0 |. E8 2F040000 CALL ; \strlen
004025C5 |. 85C0 TEST EAX,EAX ; eax=0A chieu dai Lincense code: '0123456789'
004025C7 |. 59 POP ECX
004025C8 |. 7E 13 JLE SHORT RSRemind.004025DD
004025CA |> 0FBE043E /MOVSX EAX,BYTE PTR DS:[ESI+EDI] ; eax= ky tu thu i cua License code
004025CE |. 0145 FC |ADD [LOCAL.1],EAX ; local.1=local.1+eax
004025D1 |. 56 |PUSH ESI ; /edi='0123456789'
004025D2 |. 47 |INC EDI ; |edi=edi+1 ===>counter i=i+1
004025D3 |. E8 1C040000 |CALL ; \strlen
004025D8 |. 3BF8 |CMP EDI,EAX ; eax=len License code ‘0123456789’ = 0A so sanh voi counter i
004025DA |. 59 |POP ECX
004025DB |.^ 7C ED \JL SHORT RSRemind.004025CA ; local.1=752
004025DD |> 8A8D F4FEFFFF MOV CL,BYTE PTR SS:[EBP-10C] ; cl= ky tu dau tien cua Name df =53= 'S'
004025E3 |. 5F POP EDI
004025E4 |. 84C9 TEST CL,CL
004025E6 |. 0FBEF1 MOVSX ESI,CL ; esi='S'
004025E9 |. 74 1B JE SHORT RSRemind.00402606
004025EB |. 8D85 F4FEFFFF LEA EAX,[LOCAL.67] ; eax= 'Single License'
004025F1 |> 0FBEC9 /MOVSX ECX,CL ; ecx=ky tu trong name thu i
004025F4 |. 014D F8 |ADD [LOCAL.2],ECX ; local.2=local.2+ecx
004025F7 |. 3BCE |CMP ECX,ESI ; ecx=esi ?
004025F9 |. 7E 03 |JLE SHORT RSRemind.004025FE
004025FB |. 0FBE30 |MOVSX ESI,BYTE PTR DS:[EAX] ; esi= ky tu hien ton tai
004025FE |> 8A48 01 |MOV CL,BYTE PTR DS:[EAX+1] ; cl=byte [eax+1]
00402601 |. 40 |INC EAX ; eax=eax+1
00402602 |. 84C9 |TEST CL,CL ; cl=0 khi het chuoi name df
00402604 |.^ 75 EB \JNZ SHORT RSRemind.004025F1 ;dump local.2=545 cuoi vong lap loop
00402606 |> 8B5B 08 MOV EBX,DWORD PTR DS:[EBX+8] ; ebx=const =406
00402609 |. 8D85 F4FEFFFF LEA EAX,[LOCAL.67] ; eax= name df
0040260F |. 50 PUSH EAX ; /s
00402610 |. E8 DF030000 CALL ; \eax= len name df = 0E
00402615 |. 0FAFC6 IMUL EAX,ESI ; ===> eax=eax*esi=eax*73=0E*73=64A (esi=ky tu cuoi cung cua chuoi name df la ky tu ‘s’=73h)
00402618 |. 03C3 ADD EAX,EBX ; eax=eax+ebx= eax + esi=eax+406=A50 (esi la hang so = 406)
0040261A |. 59 POP ECX
0040261B |. 2B45 FC SUB EAX,[LOCAL.1] ; eax=eax-local.1
0040261E |. F7D8 NEG EAX ; eax= neg eax
00402620 |. 1BC0 SBB EAX,EAX ; eax=eax-eax. Neu eax=FFFFFFFF===> bad boy ; eax=0 good boy
00402622 |. 40 INC EAX ; eax=eax+1
00402623 |> 5E POP ESI
00402624 |. 5B POP EBX
00402625 |. C9 LEAVE
00402626 \. C3 RETN

======================

Trong quá trình trace F8 ta thấy chương trình trial này nó ko tính tóan License Name của ta nhập vào mà nó lấy chuổi License Name default: ”Single License” để tính tóan.
Theo đọan mã cuối hàm call:

0040261B |. 2B45 FC SUB EAX,[LOCAL.1] ; eax=eax-local.1
0040261E |. F7D8 NEG EAX ; eax= neg eax
00402620 |. 1BC0 SBB EAX,EAX ; eax=eax-eax. Neu eax=FFFFFFFF===> bad boy ; eax=0 good boy
00402622 |. 40 INC EAX ; eax=eax+1

Để có Good boy thì eax=0 tại :
0040261B |. 2B45 FC SUB EAX,[LOCAL.1] ; eax=eax-local.1

Theo như trên ,vì eax=eax-local.1
Nên để eax=0 sau khi thực kiệm phép tóan trên thì : local.1=eax
Theo routine:
00402618 |. 03C3 ADD EAX,EBX ; eax=eax+ebx= eax + esi=eax+406=A50 (esi la hang so = 406)
Vậy Local.1=eax=A50
Chúng ta lại thấy trong quá trình trace:

Local.1= Tổng các ký tự Name df + Tổng các ký tự của License Code
Thay các giá trị vào:
A50= 545+ Tổng các ký tự của License Code (545 là tổng các ký tự Name df: “Single License”
Hêhê, vậy:
Tổng các ký tự của License Code= A50-545=50B
Tui chọn chuổi này “ZZZZZZZZPPPPPQ” có tồng các ký tự =50B
Chuổi này là ngắn nhất đó , có ai tìm ra chuổi ngắn hơn tui dẫn đi nhậu ....hêhê
(Để tính tổng ta các ký tự ta dùng calc.exe mà máy nào cũng có)
Vậy là OK, hảy nhập thử License code vừa tìm xem nào.
==========================

Nếu các bạn nào hiểu được ví dụ tui đã post ở trên thì …các bạn ko cần đọc tiếp nữa, vì các bạn giỏi hơn benina rồi. Còn nếu các bạn nào chưa hiểu gì nhiều cái vì dụ trên thì các bạn sẽ tìm hiểu cùng benina nhé. Chúng ta sẽ đi từng bước một thật vững chắc để có được một nền tảng căn bản về cracking.
Trước khi đi tiếp các bài sau, tui xin nhắc lại, các bạn hảy đọc kỹ bài UseOlly phần 2 của anh RongChauA và hảy thử debug chương trình trên và tìm hiểu xem tại sau benina comment như trên để có một cái nhìn bao quát về this traget. Điều quan trọng nhất khi đọc các bài tut về Find Real Serial là các bạn vừa đọc, vừa thực hành thì các bạn sẽ hiểu được những gì các tác giả commeting. Học cracking mà ko thực hành thì …. Xin mời các bạn vào mục Recycle Bin mà đọc.
Thưa các bạn , tui có vào một số forum về “tình yêu “ hay đại lọai như thế và hay gặp những lời cảnh cáo của các Admin như “Bạn câu bài , tui sẽ warm bạn nếu tái phạm”…v…v… Như ở đây, trong lọat tut này , ko biết có ai nghĩ benina câu bài ko nửa. Nhưng thật sự mà nói, benina ko có khái niệm về cái gọi là “câu bài” . Mà những bài benina posted là những gì benina tìm hiểu được khi học cracking. Nó cũng là những gì benina hệ thống cho chính bản thân mình, đồng thời muốn chia sẽ cho các bạn . Vì benina thật sự rất bận, nên khi nào rãnh rỗi mới dịch và viết được vài bài. Mong các bạn và các admin thông cảm mà đừng cho rằng em “câu bài”.
Đến đây thì khúc dạo đầu đã xong. Chúng ta sẽ tiếp tục với TUT sau về các khái niệm căn bản của ASM và tìm hiểu xem những gì các cracker commenting khi viết TUT về Find Real Searial.

BÀI 5: FIND REAL SERIAL
PHẦN 2: VÀI QUI TẮC CƠ BẢN TÌM SERIAL


V mến
Hôm nay anh mới trả lời thư cho em được. Bận quá xá. Sorry nhe.
Thực ra , tìm serial dễ lắm. Không khó đâu. Em cứ bình tỉnh.Rồi sẽ tìm được thôi. Anh sẽ chỉ em một số nguyên tắc cơ bản như sau:

1. Đầu tiên chúng ta đặt bp , khi đó chúng ta sẽ chốt được "điểm đầu " và "điểm cuối " của quá trình kiểm tra serial. Theo kinh nghiệm của anh, "điểm cuối" hay còn gọi là "tử huyệt" là quan trọng nhất. Vì từ đây chúng ta sẽ truy ngược các hàm call từ dưới lên trên. Vì real serial thường xuất hiện gần "tử huyệt" nên "bóp đít" quan trọng hơn "nằm đầu" là vậy.Nói chung chúng ta bắt buộc phải biết 2 điểm "đầu" và "cuối" . Đây là một số cách :
Nếu chúng ta chỉ biết điểm đầu mà chưa biết điểm đích thì chúng ta cứ trace , đến khi xuất hiện thông báo bad boy thì đó là điểm đích....
Nếu chúng ta biết điểm đích mà chưa biết điểm đầu ở đâu thì chúng ta cứ “ mò lên” vùng code và đặt bp tại hàm call nào chúng ta nghi ngờ. Khi đó chúng ta sẽ có “điểm đầu “ giả tạo. Nếu chưa tìm ra real serial , thì chúng ta cứ dời điểm đầu lên trên chút nữa, cứ thế, cứ thế
Tóm lại có rất nhiều cách tìm điểm đầu và đích.

2.Trong quá trình trace lúc đầu thì thường chúng ta ko thấy real serial . Vì có một số điểm "rào cản" . Nếu chúng ta vượt ra được các điểm "rào cản" này thì chúng ta mới hy vọng tìm ra real serial. Vậy điểm “rào cản” này là gì?. Anh lấy ví dụ:
Như name chúng ta nhập vào có 6 chử như Name:"benina" chẳng hạn ,nhưng chương trình lại qui định name nhập vào phải có 8 ký tự. Đó chính là điểm “rào cản" để tìm real serial. Hiểu điểm “rào cản” rồi nhé .
Anh lấy ví dụ soft NXPowerLite 1.53 : điểm “rào cản” quan trọng của softs này là cho 1 chuổi mẫu( em sẻ thấy chuổi này xuất hiện trong cửa sổ stack hay cửa sổ FPU (cửa sổ thanh ghi) trong quá trình trace). Chuổi serial chúng ta nhập vào phải có thứ tự tăng giảm như chuổi mẫu và có 25 ký tự . Vì vậy chúng ta sẽ lấy 25 ký tự của chuổi mẫu nhập vào làm fake serial thì sẽ qua được điểm rào cản này.
Tóm lại : để tìm các điểm rào cản , chúng ta phải trace từ “điểm đầu” xuống chắc chắn chúng ta sẽ tìm được các điểm “rào cản”. Nếu ko qua điểm điểm rào cản thì nó sẽ nhảy đến bad boy ngay lập tức.
Một cách vượt qua điểm “rào cản” không chính qui là chúng ta patch các hàm jump trong quá trình trace. Cách này có khi lại qua “điểm rào cản” được đấy . Nhưng ko nên dùng cách này. Hảy cố tìm ra nguyên tắc của điểm rào cản như vậy tốt hơn.

3.Một số dạng Real serial :
Nếu chúng ta vượt qua được điểm rào cản để đến phần tính toán real serial. Thì sẽ có một số dạng serial đơn giản như sau:
Dạng dễ nhất: Soft sẽ lấy serial chúng ta nhập vào so sánh với real serial mà chương trình tạo ra. Vì vậy , chắc chắn real serial sẽ chứa đâu đó trong memory. Do đó đối với Olly, trong quá trình trace chúng ta sẽ bắt gặp nó nằm đâu đó trong cửa sổ thanh ghi, hay nằm đâu đó trong cửa sổ stack của Olly. Vì vậy trong quá trình trace , nếu chưa hiểu thuật toán của softs , chúng ta thấy xuất hiện bất cứ chuổi nào trong stack hay trong cửa sổ thanh ghi chúng ta cứ nhớ nó = cách copy ra 1 file text nào đó. Rồi sau đó cứ nhập thử vào , có khi chúng ta hên sẽ biết được real serial. Cách này Anh gọi nôm na là tìm trong “đóng rác” là vậy. hihi
Một số thuật toán như MD5 cũng thuộc dạng này. Nó tính toán rất ghê góm, nhưng đến một lúc nào đó nó cũng xuất hiện chuổi real serial trong của sổ stack… hihi
Dạng Fixed Password: Như các soft bác kienmanowar đã crack của trang web emailarms.com. Tức là chuổi real serial phải có một số vị trí ký tự qui định sẳn. Loại soft này ko xuất hiện chuỗi real serial trong cửa sổ stack . Đặc điểm của các softs này là sẽ có một chuổi các điểm “rào cản” liên tiếp nhau để đi đến tử huyệt. Nếu chúng ta biết được điểm đích thì chúng ta sẽ dễ dàng tìm ra “chuổi điểm rào cản này” .
Một dạng nữa : (dạng này cũng ko hiện chuổi serial trong stack) dạng này là tính toán name và chuổi serial chúng ta nhập vào theo 1 “qui tắc” nào đó thành một con số (như softs Ripple Screensaver 3.0 trong bài 4 Let’s crack by Olly) , rồi đem so sánh với một số nào đó . Dạng này hơi khó, vì chúng ta phải hiểu quá trình tính toán tức là phải hiểu “quy tắc” tính toán. Dạng này nếu là newbie chúng ta chỉ patch tại điểm so sánh là xong (hoặc patch AL=1 hay EAX=1 cuối hàm call như hacnho đã làm ). Nếu patch mà khi vào lại vẫn bị báo reg , thì chắc rằng sẽ có một quá trình tính toán tương tự ở đâu đó trong chương trình. Chúng ta cố tìm ra để patch nó thì sẽ OK .
Vân vân và vân vân…..rất nhiều dạng….
Một quy tắc rất quan trọng để tìm serial cho nhanh:
Vì trong một đóng code chúng ta trace hết thì rất mệt mỏi. Vậy làm sao để đến các điểm “rào cản” và các “qui tắc” tính toán chuổi serial cho nhanh. Chúng ta hảy để ý như sau: khi đến các điểm “rào cản” hay các điểm bắt đầu “quy tắc tính toán” chuổi serial thì chương trình lúc nào cũng phải chạm đến vùng nhớ chứa chuổi serial chúng ta nhập vào để lấy nó ra tính toán. Vì vậy chúng ta sẽ đặt bp trên vùng nhớ chứa serial khi chương trình acess đến nó. Ví dụ :
Khi chúng ta biết được “điểm đầu”.Lúc đó chuổi serial chúng ta nhập vào đã nằm đâu trong memory đúng ko?. Chúng ta sẽ tìm xem chuổi serial của chúng ta nhập vào nằm đâu trong memory = cách nhấn ALT-M mở cửa sổ memory. Và search (CTRL-B) tìm chuổi serial. Khi đó chúng ta chọn chuổi tìm được và đặt breakpoint /memory, on acess trên vùng nhớ serial, tức là khi nào chương trình chạm đến vùng nhớ đó sẽ ngắt.Khi đó chúng ta sẽ đến các điểm “rào cản “ rất nhanh.

Benina (http://www.reaonline.net)

[Anti Virus] Demo phương pháp nhận dạng virus giả dạng thư mục

RefLink: http://virusvn.com/forum/showthread.php?p=14529#post14529

Posted by DungCoi:

Dựa trên code cũ mình sử dụng trong project QuickVK, lần này mình chỉnh lại một số yếu tố :
- Chỉnh lại kích thước icon : Icon cũ 48x48 pixel, icon mới dùng 32x32 pixel
- Chỉnh lại một số tham số
- Chỉnh lại cái giao diện cho bớt rối


Không quá nhiều thay đổi. Số lượng icon sử dụng để nhận dạng là 1 icon duy nhất.
Sau đây là kết quả thực nghiệm :


(1) : Số mẫu virus giả dạng thư mục
(2) : Số các icon khác nhau trong các mẫu Virus giả dạng thư mục (Nhiều dòng virus có thể dùng chung 1 icon)

Sau đây là hình ảnh demo


Scan : C:\


Scan : …\Sample\FakeFolder

Bạn có thể tải chương trình demo trong file đính kèm

Cùng nhau test để xem nó nhầm nào

Posted by Gianghoplus:


Thank dungcoi. Scan với đống sample của mình thì nó detect được hơn 70%, tuy nhiên cách quét khá chậm

Mình cũng mạo muội xin chia sẻ 1 số "mánh" của mình để detect những mẫu virus này. Nói chung là rất hiệu quả nếu quét USB (chưa thấy trường hợp nhầm)

Ở đây mình có viết 3 hàm:
- bool IsHiddenFile()
- int SameFolderIcon() -> (trả về % tỉ lệ giống với icon folder)
- bool PathIsRemovableDisk()

Nhập cuộc:

Scan File:

Heuristic 1 (Ex: Z:\Image\ & Z:\Image\Image.exe)
Mô tả điều kiện:
+ Có 1 tập tin .exe giống tên với thư mục cha chứa nó

Điều kiện bổ sung:
+ SameFolderIcon() > 50%
+ Có ít nhất 2 bản sao của file này dính Heur bất kì

Heuristic 2 (Ex: Z:\Image.exe & Z:\Image\)
Mô tả điều kiện:
+ Có 1 tập tin .exe giống tên với 1 thư mục cùng mức
+ Thư mục đó bị ẩn.

Điều kiện bổ sung:
+ SameFolderIcon() > 75%
+ Có ít nhất 2 bản sao của file này dính Heur bất kì

Heuristic 3
Mô tả điều kiện:
+ SameFolderIcon() > 90%
+ Có ít nhất 3 bản sao của file này dính Heur bất kì

Heuristic 4 (Ex: Folder shortcut A, B, C, ... => Hidden file )
Mô tả điều kiện:
+ Có nhiều shortcut (nằm cùng mức) cùng trỏ về 1 tập tin .exe
+ Icon hiển thị của shortcut đó có thuộc tính SameFolderIcon() > 50%
+ Tập tin .exe được trỏ về có thuộc tính IsHiddenFile() == true

Heuristic 5 (Executable files hidden on USB)
Mô tả điều kiện:
+ Trong RemovableDisk có tập tin thực thi có thuộc tính ẩn
+ PathIsRemovableDisk() == true
+ IsHiddenFile() == true

Điều kiện bổ sung:
+ SameFolderIcon() > 40%

Heuristic 6 (Ex: Z:\autorun.inf & Z:\autorun.exe)
Mô tả điều kiện:
+ Tồn tại 1 tập tin autorun.inf nằm trong RemovableDisk hoặc HardDisk
+ Trỏ tới 1 file .exe, .pif, .src, .bat .... có thể thực thi

Scan Memory

Heuristic 1
Mô tả điều kiện:
+ Tập tin thực thi của tiến trình dính bất cứ Heur nào ở trên

Heuristic 2
Mô tả điều kiện:
+ Tập tin thực thi của tiến trình có thuộc tính IsHiddenFile() == true

Điều kiện bổ sung:
+ SameFolderIcon > 50%

Heuristic 3
Mô tả điều kiện:
+ SameFolderIcon() > 90%

Real-time detect

Heuristic 1 (Detecting action)
Mô tả điều kiện:
+ Tiến trình có hành động tạo file autorun.inf hoặc tự sao chép mình vào RemovableDisk.

Một số kĩ thuật của Heur này:
+ Checksum & Compare
+ Hook API (Ex: CreateFile, CopyFile, ...) sau đó dựa vào GetCurrentThreadId() hoặc GetCurrentProcessId() để xử lý tùy vào trường hợp

Heuristic 2 (Detecting action)
Mô tả điều kiện:
+ Có hành động sửa đổi giá trị một số vùng nhạy cảm của Registry (Ex: UserInit, Show/Hide file of Folder Option, ...)

Một số kĩ thuật của Heur này:
+ Hook API (Ex: RegSetValueEx ...) sau đó dựa vào GetCurrentThreadId() hoặc GetCurrentProcessId() để xử lý tùy vào trường hợp


Tạm thời post chừng đó đã, đến giờ cơm trưa rồi

Những "ngu kiến" nhận dạng Heur trên là do gianghoplus tự tổng hợp và suy luận được trong thời gian nghiên cứu về dòng virus autorun này. Có thể nó ko hoàn toàn chính xác hoặc có nhiều điểm chưa hợp lý, mong các bác chân thành đóng góp ý kiến hoặc bổ sung

Thân !

@Dungcoi: Share cho mình đống sample fake folder của cậu nhá


Posted by DungCoi:

Chỉnh lại thêm một tý.
Tỷ lệ nhận dạng là : 47/48 (1 icon có hình thù hơi mới mẻ )
Vẫn chưa thấy trường hợp nhầm trong máy mình.

Lại nhờ các bạn test tiếp
GiangHo test dùm xem có lên được % nào không

Mình vừa nhận được 20 sample từ GiangHo.
GiangHo chịu khó xem lại chút, nếu nhiều sample có thuộc tính System thì tất nhiên app phải có quyền Admin mới xử lý lấy icon được thì phải.

Mình vừa thử 2 cách :
1. Cho app chạy quyền Admin
2. Bỏ thuộc tính System trong các sample


Kết quả của 48 mẫu của mình + 20 mẫu từ GiangHo = 68 mẫu



Vẫn bỏ xót một mẫu có kiểu hình icon khác so với icon mình dùng để detect (Nếu giảm các tham số truyền vào cũng được nhưng như vậy sẽ mất tính an toàn)


PS : Do chương trình viết bằng VB6 chạy vài thứ liên quan tới đồ họa không tương thích ổn với Win7 + Vista nên để chương trình chạy ổn định bạn làm 2 thao tác sau
1. Chuột phải vào chương trình chọn Properties -> Chọn thẻ Compatibity -> Nhấn dấu chọn Disable desktop composition
2. Cho chương trình chạy quyền admin (Chuột phải chọn Run as Administrator)


Dowload: http://megashare.vn/dl.php/1230789

5/30/10

[Symbian] Chương trình hoạt động trên Symbian 2

Leave-Symbian exeption

1. Cơ chế bắt lỗi trên Symbian:
Nếu bạn đã quen với lập trình C++ hay Java thì exeption handling là một khái niệm chẳng xa lạ gì. Đây là cơ chế giúp ta quản lý các lỗi phát sinh. Lúc Symbian được thiết kế thì cơ chế exeption chưa được giới thiệu trong C++ hơn nữa sau này khi được giới thiệu thì nó cũng tỏ ra không phù hợp trong môi trường hạn chế về xử lý và bộ nhớ như Symbian bởi chúng làm tăng đáng kể kích thước mã biên dịch và tốn nhiều RAM, lại không thật sự hiệu quả.
Vì vậy Symbian đã đưa ra một cơ chế quản lý lỗi cho riêng mình được biết dưới tên gọi "leave". Do đó tuy Symbian sử dụng cú pháp C++ nhưng không hề có từ khóa try, catch hay throw đâu, các bạn nên chú ý điều này.
Trong một môi trường mà tài nguyên hạn hẹp như Symbian thì một cơ chế bắt lỗi hiệu quả và ít tốn kém sẽ rất cần thiết. "Leave" đã đáp ứng điều này. Cơ chế hoạt động của "leave" như sau: khi xảy ra một lỗi nào đó (thiếu bộ nhớ để cấp phát, thiếu vùng nhớ để ghi, lỗi trong truyền thông hay thiếu năng lượng cho các tài nguyên,...) thì hàm đang hoạt động sẽ bị ngắt lại, quyền điều khiển sẽ được chuyển đến phần chỉ thị sửa lỗi.
Xét về mặt cú pháp thì cơ chế "leave" này khá tương đồng với cơ chế của C++. Hàm đang thực thi bị ngắt bởi một cuộc gọi đến hàm User::Leave() hay User::LeaveIfError() khá giống với throw trong C++ còn 2 marco TRAP và TRAPD trên Symbian thì tương đồng với try và catch trên C++.
Ví dụ:
TInt result;
TRAP(result, MyLeaveL());
if (KErrNone==result)
{
//Code
}
User::LeaveIfError(result);

2. Hàm leave:
Như tôi đã nói trong phần quy ước trên Symbian, hàm có thể leave thì sẽ kết thúc bằng chữ L. Một hàm có thể leave nếu nó:
- Gọi hàm có thể leave mà không được gọi kèm với các trap harness như TRAP hay TRAPD.
- Gọi một trong các hàm hệ thống đảm nhận leave nhu User::Leave() hay User::LeaveIfError(),...
- Có dùng toán tử new(Eleave).
Chắc có lẽ có nhiều bạn sẽ thắc mắc tại sao tôi lại quá chú trọng đến "leave" như vậy. Thật ra "leave" là một khái niệm rất cơ bản trên Symbian bởi vì: thứ nhất, nguồn tài nguyên trên Symbian khá hạn hẹp nên lỗi thiếu tài nguyên hay xảy ra, thứ 2, nếu bạn không chú ý kỹ đến nó, nhất là phần thế nào là một hàm leave thì bạn sẽ gặp phải lỗi rất lớn trong lập trình trên Symbian: làm "lủng" bộ nhớ. Chi tiết về điều này mời các bạn xem bài sau: Cleanup stack.

Cleanup stack

Tại sao trong bài trước tôi lại nói nếu bạn không chú ý đến quy ước cũng như xem xét hàm của bạn có phải là hàm leave hay không thì có thể code bạn viết gây "lủng" bộ nhớ, đó là vì: nếu hàm của bạn có leave xảy ra thì tại thời điểm leave, điều khiển sẽ được chuyển đến phần xử lý lỗi, lúc này vùng stack cho hàm có leave này sẽ được giải phóng, các biến khai báo cục bộ trong hàm này sẽ bị xóa đi. Đối với các biến khai báo kiểu T trên stack thì không sao nhưng đối với các biến kiểu C khai báo trên heap hay các biến kiểu R thì đây là vấn đề nghiêm trọng. Bởi lẽ theo đúng quy trình thực thi, nếu không có gì xảy ra thì vào cuối hàm, chúng ta sẽ hủy vùng nhớ đối tượng trên heap qua toán tử delete hay gọi hàm Close() cho các biến kiểu R nhưng nếu giữa chừng hàm bị ngắt trước khi ta gọi các hàm hủy này thì rõ ràng các đối tượng này sẽ không được giải phóng hoàn toàn, tạo ra lỗ hổng trên bộ nhớ.
Ví dụ:
void UnsafeFunctionL()
{
CExClass* test = CExClass::NewL(); //Hàm có thể leave
test->FunctionMayLeaveL();
delete test;
}
Điều gì xảy ra khi hàm FunctionMayLeaveL() bị leave, lúc này hàm UnsafeFunctionL() sẽ bị ngắt, stack sẽ bị xóa, biến test bị bị xóa nhưng vùng nhớ cấp cho nó trên heap qua hàm CExClass::NewL() thì vẫn còn và lúc này không ai quản lý nó cả, nó bị "mồ côi" trên heap. Vùng nhớ cấp phát này sẽ tồn tại mà không được giải phóng tại ra một lỗ hổng trong bộ nhớ.
Vậy bây giờ ta phải làm sao đây để luôn đảm bảo không bị lỗ hổng trên bộ nhớ khi có leave xảy ra? Symbian đã đưa ra khái niệm mới là Cleanup Stack.
Cleanup stack là một ngăn xếp có nhiệm vụ giải phóng các vùng nhớ cấp cho các đối tượng được đưa vào chúng trước đó khi leave xảy ra.
Ví dụ: dùng hàm trên với cleanup stack:
void SafeFunctionL()
{
CExClass* test = CExClass::NewL(); //Hàm có thể leave
CleanupStack:: push(test);
test->FunctionMayLeaveL();
CleanupStack:: pop(test);
delete test;
}
Lúc này nếu có leave xảy ra thì chúng ta vẫn không sợ bị lủng bộ nhớ vì cleanup stack đã giải phóng vùng nhớ cho biến test giùm chúng ta rồi nhờ hàm: CleanupStack:: push(test).
- Một lưu ý là nếu leave không xảy ra thì chúng ta phải lấy đối tượng cần hủy ra khỏi cleanup stack qua hàm CleanupStack:: pop(test) (chúng ta có thể dùng nhiều cách pop khác nhau, chi tiết các bạn xem qua lớp CleanupStack).
- Một lưu ý khác là với những hàm kế thúc bằng LC, nghĩa là có thể leave và đã có push lên cleanup stack rồi, nên sau khi gọi hàm này, bạn phải gọi hàm CleanupStack:: pop() hoặc CleanupStack:: popAndDestroy() nếu không sẽ bị lỗi. Lỗi này tôi cũng đã nói trong phần quy ước rồi, các bạn chú ý nhé, hay bị lỗi này lắm đó.
- Đối với các đối tượng kế thừa các lớp khác ngoài lớp C thì khi hủy cleanup stack chỉ có thể hủy vùng nhớ mà không thể gọi destructor như đối với lớp C được nên Sym bian đề xuất một số hàm push khác cho phù hợp: CleanupReleasePushL() để chỉ giải phóng vùng nhớ (đối tượng lớp T), CleanupDeletePushL() để chỉ thực thi destructor (đối tượng lớp M) hay CleanupClosrPushL() để giải phóng tài nguyên cấp cho các đối tượng lớp R.
Leave và Cleanup stack là một cặp bài trùng tạo nên sự an toàn cho lập trình trên Symbian. Đây là 2 khái niệm rất cơ bản, nếu không hiểu vè nó, trong khi lập trình có thể bạn sẽ gặp lỗi mà không biết đường sửa hay có thể gặp vài lỗi rất ngớ ngẫn.


Two-phase construction

Đến đây chắc bạn đã thấy là Symbian hỗ trợ quản lý bộ nhớ tốt như thế nào, đảm bảo cả trong điều kiện lỗi vẫn không bị lủng bộ nhớ. Lý do khiến Symbian rất chú trọng đến việc này là so với PC, điện thoại di động có bộ nhớ không lớn bằng hơn nữa các ứng dụng trên điện thoại đôi khi phải chạy hàng tháng, thậm chí hàng năm (nếu ta không tắt máy).
Từ bài cleanup stack, có người thắc mắc là có phải tất cả các lớp đều có hàm NewL() và NewLC() để khởi tạo đối tượng không và nhận thấy mình thiếu một phần quan trọng đi liền sau leave và cleanup stack là khởi tạo 2 pha (two-phase construction) nên hôm nay tôi sẽ nói về nó luôn, tạm gác phần descriptor lại.

1 Two-phase construction:
Theo đúng cú pháp C++, một đối tượng mới sẽ được cài đặt như sau:
Code:

CExam* exam = new (Eleave) CExam();

Hệ thống sẽ làm gì với code trên: đầu tiên, một vùng nhớ sẽ được cấp trên heap cho đối tượng lớp CExam nhớ hàm new, rồi sau đó constructor của lớp CExam sẽ được gọi để hoàn tất việc khởi tạo đối tượng. Điều gì sẽ xảy ra nếu hàm constructor của lớp này bị leave, rõ ràng là bộ nhớ sẽ bị lủng do heap đã cấp một vùng cho đối tượng foo rồi và như vậy vùng nhớ này sẽ bị "mồ côi" trên heap. Lúc này ắt hẳn có bạn sẽ nghĩ ngay đến cleanup stack, nếu được như vậy thì tôi rất mừng vì bạn đã biết vai trò của cleanup stack ở chỗ nào, thế nhưng tiếc thay trong trường hợp này lại không dùng được. Tai sao ư? Tại vì để làm được điều đó thì hàm CleanupStack:: push phải đặt trong lòng toán tử new, điều này có thể sao?!
Vì vậy Symbian đưa ra một luật là: constructor không được phép leave. Nhưng đôi khi trong phần khởi tạo của chúng ta lại có phần có thể leave thì sao, chẳng hạn như cấp phát bộ nhớ hay tạo một session truy cập tài nguyên. Trong tình huống đó, khởi tạo 2 pha (two-phase construction) sẽ giúp bạn:
- Pha 1: Phần constructor đơn giản, không leave. Phần này sẽ được gọi liền ngay sau khi toán tử new được gọi.
- Pha 2: Một hàm khác sẽ đảm nhận việc hoàn tất khởi tạo, trên Symbian thường đặt tên là ConstructL(), hàm này có thể leave.
Code:

CExam* exam = new (Eleave) CExam();//pha 1 CleanupStack:: push (exam); exam->ContructL();//Pha 2 CleanupStack:: pop();

Và bây giờ thì ta đã yên tâm là bất cứ có gì xảy ra, bộ nhớ vẫn nguyên vẹn.

2. NewL() và NewLC():
Nhưng cách trên bất tiện ở chỗ là khi khởi tạo 1 đối tượng lại phải gọi 2 pha với 4 hàm, vừa bất tiện vừa dễ quên. Do đó Symbian tiếp tục đưa ra một khái niệm nữa để giúp cho lập trình viên chúng ta tránh được sự hay quên và dài dòng này.
Trong lớp CExam, chúng ta tạo thêm 2 hàm tĩnh (có từ khóa static đằng trước phần khai báo thông thường) NewL() và NewLC() như sau:
Code:

CExam* CExam::NewLC() { CExam* me = new (Eleave) CExam();//pha 1 CleanupStack:: push (me); exam->ContructL();//Pha 2 return me; } CExam* CExam::NewL() { CExam* me = CExam::NewLC(); CleanupStack:: pop (me); return me; }

Và lúc này việc khai báo đối tượng của bạn sẽ vừa dễ dàng lại đảm bảo:
Code:

CExam* exam = CExam::NewL();

Lưu ý: Ở trên các bạn thấy tôi luôn xài Eleave sau toán tử new. Nhờ nó mà nếu không cấp phát được, leave sẽ xảy ra. Nếu không có nó rõ ràng sau hàm new bạn phải kiểm tra xem có cấp phát thành công không, rất mất công lại làm code phức tạp thêm.
Code:

CExam* exam = new (Eleave) CExam(); if (NULL != exam) { //cấp phát thành công }

Tóm lại: Nếu trong hàm constructor mà không có gì để gây ra leave cả, thì các bạn cứ xài như đã từng xài trước đây, nghĩa là dùng code như C++ vậy. Nếu trong hàm constrcutor này mà có leave thì bạn mới phải cần đến two-phase construction.

Chuỗi trên Symbian: Descriptor

Trên Symbian, chuỗi được gọi là descriptor bởi chúng tự mô tả (describe): một descriptor chứa kích thước, kiểu chuỗi bên cạnh nội dung chuỗi trong vùng nhớ. Đây là điều mà chuỗi trong C/C++ hay Java không có.
Descriptor được xây dựng theo hướng tối ưu hóa vùng nhớ cấp phát, điều rất cần trên các môi trường bộ nhớ thấp như Symbian. Nhưng cũng chính vì điều này mà descriptor làm đau đầu khá nhiều lập trình viên về việc sử dụng chúng.
Từ version 5.0 trở về trước, Symbian chưa hỗ trợ Unicode nên descriptor chỉ hỗ trợ chuỗi với ký tự 8 bit, nhưng từ v5.1 trở về sau thì descriptor trên Symbian hỗ trợ cả 8 bit và 16 bit (Unicode). Một điểm đặc biệt nữa là descriptor không sử dụng ký tự đặc biệt để kết thúc chuỗi như trên C/C++ hay Java, nên dữ liệu chúng chứa có thể là dữ liệu nhị phân. Việc sử dụng chung descriptor cho lưu trữ ký tự và nhị phân rõ ràng sẽ làm nhỏ gọn lại Symbian và tiện lợi cho người dùng. Lưu ý là khi muốn lưu trữ nhị phân, bạn phải khai báo descriptor ở dạng 8 bit.

1. Descriptor hằng:
Tất cả các kiểu descriptor trên Symbian đều kế thừa TDesC (typedef của TDesC16, xem e32std.h) và được định nghĩa trong e32des16.h (thư mục: epoc32\include). Bản 8 bit là TDesC8 (e32des8.h). Như đã giới thiệu: C kết thúc lớp báo hiệu đây là lớp hằng, dữ liệu không đổi.
Trên vùng nhớ , một descriptor được lưu trữ như sau: 4 byte đầu lưu trữ chiều dài (thật ra chỉ 28 bit trong số 32 bit (4 byte) là lưu trữ chiều dài chuỗi, do đó chuỗi tối đa mà ta có thể chứa trong descriptor là 2^28 byte, 256 MB, 4 bit cao còn lại chứa kích thước của đối tượng descriptor, đây là cơ sở để xác định kiểu descriptor.
Với 4 bit chúng ta có thể phân biệt 16 kiểu descriptor nhưng trên Symbian chỉ có 5 loại). Phần tiếp theo sẽ lưu trữ dữ liệu descriptor hay con trỏ chỉ đến vùng lưu trữ thật sự.
Lấy chiều dài thông qua hàm Length(), trong khi truy cập dữ liệu thì nhở vào hàm Ptr(). Đây là 2 hàm ảo quan trọng nhất, từ đây TDesC sẽ cài đặt tất cả các hàm liên quan cho descriptor như truy cập dữ liệu, so sánh chuỗi, tìm kiếm, ...

2. Descriptor "động":
"Động" ở đây mang nghĩa là dữ liệu chưa trong descriptor có thể thay đổi. Tất cả các descriptor động đều kế thừa từ TDes. Về mặt lưu trữ, descriptor động giống như descriptor hằng, chỉ có thêm thành phần chứa chiều dài tối đa của chuỗi dữ liệu. Hàm MaxLength() sẽ trả về giá trị này.
TDes định nghĩa một loạt các phương thức phục vụ cho việc thay đổi dữ liệu như thêm, chèn, hay định dạng dữ liệu,... Một đặc điểm đáng lưu ý là một khi đã khai báo chiều dài tối đa thì không sao thay đổi được, do TDes và các lớp kế thừa từ nó đều không có hàm phục vụ cho việc cấp thêm bộ nhớ nên khi thêm dữ liệu, bạn phải lưu ý là dữ liệu thật sự lưu không bao giờ được vượt quá max length, nếu không bạn sẽ gặp phải lỗi.
Trên đây tôi đã giới thiệu về 3 lớp cơ bản về descriptor, TDes16, TDes8 và TDes (dạng trung tính dùng cho mục đích tương thích, hiện nay TDes luôn là TDes16 như tôi có nhắc ở trên). Đây là các lớp cơ sở của tất cả các lớp descriptor khác, chúng chủ yếu cung cấp các hàm thao tác cho các descriptor hằng cũng như động khác hơn là phục vụ cho mục đích lưu trữ dữ liệu như các lớp dẫn xuất khác. Do đó, bạn sẽ thấy chúng chủ yếu ở vai trò làm tham số hay kết quả trả về nhằm mục đích phục vụ cho lập trình tránh bị phụ thuộc loại descriptor cụ thể (đặc điểm độc đáo của lập trình hướng đối tượng). Một điểm nữa củng cố cho điều trên là bạn không thể khai báo trực tiếp một đối tượng kiểu TDesC hay TDes được do constructor của chúng là hàm protected.

Tiếp theo chúng ta sẽ tìm hiểu hai loại descriptor: buffer descriptor, với phần dữ liệu chứa trong descriptor sau phần chiều dài, và pointer descriptor với phần dữ liệu chứa nơi khác, sau phần chiều dài trong descriptor chỉ chứa địa chỉ vùng nhớ noi thật sự lưu dữ liệu.

rước khi tìm hiểu 2 loại descriptor, chúng ta sẽ tìm hiểu về literal descriptor, một loại descriptor đặc biệt.

1. Literal descriptor:
Đây là một loại descriptor hằng, gần giống với static char [] trên C. Chúng thường được dùng dưới dạng các macro gồm 3 dạng _LIT, _L và _S (đây là 3 dạng trung tính, thật sự là _LIT16, _L16, _S16, _LIT8, _L8, _S8 phục vụ chuỗi 16 và 8 bit) bạn có thể tìm thấy các khai báo macro này ở e32def.h.
- _LIT macro: khai báo như sau:
Code:

_LIT(KHello, "Hello World!");

Với khai báo như vậy, KHello được xem là tên 1 đối tượng TLITC16, nó sẽ chỉ đến một đoạn dữ liệu nhị phân của chương trình chứa nội dung cần lưu trữ, trong trường hợp này là chuỗi "Hello World!". Lưu ý là khi biên dịch, trên file nhị phân chương trình, sau chuỗi "Hello World!" có ký tự kết thúc chuỗi '\0'. Và thông thường file chương trình nạp trên ROM (các ứng dụng hệ thống) nên người ta thường nói là _LIT tạo chuỗi lưu trên ROM. Lúc này thông qua tên đối tượng TLIT16 là KHello, bạn có thể hoàn toàn sử dụng nó như là một descriptor hằng.
- _L macro: khai báo như sau:
Code:

_L("Hello World!")

;
Cũng giống như ở trên, với khai báo _L, một vùng dữ liệu trên file chương trình được dùng để chứa chuỗi khai báo, nhưng khác với ở trên, chúng không có tên, không có gì để nắm giữ, điều khiển chúng. Trong trường hợp này, hệ thống sẽ tạo một pointer descriptor là TPtrC trên stack (chúng ta sẽ nghiên cứu TPtr sau) tạm thời đảm nhận việc kiểm soát và xử lý chuỗi dữ liệu này. Hiện nay, Symbian đã đề xuất bỏ kiểu khai báo này do tốn thêm stack cho đối tương tạm TPtr và chi phí khởi tạo nó. Tuy nhiên nhờ ưu điểm là giảm code lại khỏi phải đặt tên nên chúng vẫn thường được dùng với mục đích test. Ví dụ, một khi ứng dụng lỗi, để test xem có phải hàm này gây ra hay không, trên UIQ chúng ta có thể làm theo cách sau: ngay sau hàm nghi ngờ, chúng ta đặt hàm sau:
Code:

User::InfoPrint(_L("Pass"));

Nếu dòng chữ "Pass" hiện lên màn hình thì rõ ràng lỗi chắc chắn nằm sau hàm này. Cách viết này dễ hơn rất nhiều so với:
Code:

_LIT(KPass, "Pass"); User::InfoPrint(KPass));

- _S macro: Gần giống với _L, tuy nhiên nó không yêu cầu tao đối tượng tạm TPtr mà sẽ cho phép sử dụng chuỗi trực tiếp như trên C.

2. Buffer descriptor:
Đây là descriptor mà chuỗi dữ liệu chứa trong đối tượng descriptor. Chúng được chia làm 2 loại dữ trên vùng nhớ lưu trữ: stack và heap.

a. Stack buffer descriptor:
Chúng có thể là descriptor hằng hoặc động. Chúng kế thừa từ TBufCBase và TBufBase gồm TBufC và TBuf. TBufC phục vụ cho các descriptor hằng, còn TBuf cho descriptor động, n ở đây chính là khai báo cho chiều dài tối đa của chuỗi. Chúng được so sánh với char [] trên C. Ví dụ:
Code:

_LIT(KHello, "Hello World!"); TBufC<12> aHelloBufC(KHello); TBuf<15> aHelloBuf(KHello);

Lưu ý: do kích thước stack cấp cho một ứng dụng là rất nhỏ nên chuỗi cấp trên stack cũng chỉ nên cấp cho các chuỗi nhỏ, thường dưới 128 byte, nếu lớn hơn nên cấp trên heap.

b. Heap buffer descriptor:
Loại descriptor này ra đời để phục vụ cho các descriptor có kích thước lớn, không thể lưu trên stack được, và đặc biệt hữu dụng trong các trường hợp không biết rõ kích thước tại thời điểm biên dịch. Nó được dùng chủ yếu cho mục đích lưu trữ dữ liệu trong các thao tác xử lý file hay trên các kênh truyền thông: hồng ngoại hay bluetooth.
Đại diện cho descriptor này là HBufC (HBufC16 hay HBufC8), nhưng thường được sử dụng thông qua con trot, HBufC*. Vởi "C" kết thúc lớp, chúng ta biết rằng, chúng là một loại descriptor hằng. Chúng cung cấp khá nhiều hàm NewL() để tạo các đối tượng descriptor. Lưu ý là sau khi dùng xong phải hủy chúng đi vì chúng được cấp tren heap. Ví dụ:
Code:

_LIT(KHello, "Hello World!"); HBufC* iHelloBufC = HBufC::NewL(20); *iHelloBufC = KHello;//Copy nội dung KHello vào iHellBufC

3. Pointer descriptor:
Đây là loại descriptor mã dữ liệu của chúng do một descriptor khác lưu giữ, có thể trên heap, stack hay trong ROM. Chúng bao gồm 2 loại, hằng và động được so sánh với const char* và char*, được thể hiện qua 2 lớp TPtrC và TPtr. Ví dụ:
Code:

_LIT(KHello, "Hello World!"); TPtrC aHelloBufC(KHello); TPtr aHelloBuf(KHello);

Sau đây là mô hình lưu trữ 2 kiểu descriptor và sơ đồ khái quát về descriptor:
Attached Thumbnails
Click image for larger version Name: desh1.jpg Views: 59 Size: 7.7 KB ID: 29540 Click image for larger version Name: desh2.jpg Views: 52 Size: 8.5 KB ID: 29544 Click image for larger version Name: desh3.jpg Views: 68 Size: 16.3 KB ID: 29545

RefLink: http://my.opera.com/nhadautu/blog/2008/01/06/chuong-trinh-hoat-dong-tren-symbian-2

[Symbian] Chương trình hoạt động trên Symbian

1 File thực thi
Trên Symbian hỗ trợ 2 hệ thống chương trình ứng với các kiểu file khác nhau.
• Chương trình .exe: được lưu trữ trong các file thực thi có phần mở rộng là exe. Đây là chương trình với một đầu vào chính từ hàm E32Main(). Khi hệ thống nạp một chương trình .exe mới, đầu tiên nó tạo một tiến trình mới. Trong tiểu trình chính của tiến trình này, điểm vào sẽ được gọi để thực thi chương trình đó. Thông thường đây là các server hay các ứng dụng console.
• Thư viện liên kết động (Dynamic link library-DLL): một thư viện chứa các mã chương trình với nhiều điểm đầu vào. Hệ thống sẽ nạp một DLL vào trong ngữ cảnh hoạt động của tiểu trình. Có 2 loại DLL quan trọng:
- Shared DLL: cung cấp một nhóm API nhất định cho một hay nhiều chương trình sử dụng. Hầu hết các thư viện này nằm trong các file có phần mở rộng là .dll. Một chương trình thực thi sẽ được nối với thư viện dùng chung mà nó yêu cầu và khi hệ thống nạp chương trình thực thi, thư viện dùng chung cần cho chương trình này sẽ được nạp tự động.
- Polymorphic DLL: cung cấp một nhóm hàm API được lưu trữ trong các file có phần mở rộng khác nhau phục vụ cho các chức năng riêng như điều khiển máy in (.prn), giao thức socket (.prt), hay đó là một ứng dụng đồ họa GUI (.app). Trong hệ điều hành Symbian, polymorphic DLL thường chỉ có một điểm vào, nó khai báo và khởi tạo một lớp dẫn xuất từ các lớp cơ sở trong DLL này. Thư viện DLL loại này được nạp bởi chương trình sử dụng nó.
Hệ điều hành Symbian quản lý chương trình .exe và DLL khác nhau: chương trình .exe là không thể chia sẻ trong khi DLL thì hoàn toàn có thể.

2 Nạp chương trình khi thực thi
Các file thực thi chứa 3 loại dữ liệu nhị phân: mã chỉ thị, dữ liệu chỉ đọc (hằng) và dữ liệu động (thay đổi được).
• Chương trình .exe: Khi chương trình .exe được nạp vào RAM từ file .exe được lưu trên RAM (đĩa C) hoặc từ thẻ nhớ (đĩa D), thì nó được cấp một vùng nhớ riêng cho mã, dữ liệu chỉ đọc, dữ liệu động. Nếu một phiên bản thứ 2 của chương trình được nạp vào RAM thì một vùng nhớ mới sẽ được cấp cho nó. Với file chương trình .exe chứa trong ROM (ổ đĩa Z) thì chỉ có dữ liệu động được nạp vào RAM, mã chỉ thị và dữ liệu chỉ đọc được đọc trực tiếp từ ROM.
• Thư viện DLL: Khi một thư viện DLL lần đầu tiên được nạp vào RAM, nó được cấp một vùng nhớ riêng, khi được yêu cầu sử dụng lần thứ hai, nó không nạp tiếp DLL này vào RAM mà đơn giản chỉ gắn địa chỉ nó trên RAM cho tiểu trình yêu cầu. Hệ điều hành Symbian kiểm tra số lượng tiểu trình tham khảo DLL này và giải phóng nó khi không còn tiểu trình nào sử dụng nó nữa. (Đó là lý do mà các ứng dụng đồ họa Symbian, là một loại polymorphic DLL, không hề có chức năng exit, nhất là các ứng dụng hệ thống vì việc thoát nó sẽ do hệ thống đảm trách khi thiếu RAM cho các ứng dụng khác) Với các DLL chứa trên ROM thì nó không cần nạp vào RAM nữa mà được sử dụng trực tiếp trên ROM.
Việc các ứng dụng lưu trữ trên ROM không cần nạp vào RAM khi thực thi là đặc điểm của Symbian để phù hợp với tài nguyên bộ nhớ giới hạn của điện thoại. Ngoài ra để tối ưu hóa kích thước chương trình, hệ điều hành Symbian sử dụng điểm vào của DLL là một số thứ tự, trên các hệ điều hành khác có thể dùng số thứ tự hay tên. Do đó khi nâng cấp DLL thì số thứ tự phải giống như phiên bản trước.

3 Thực thi ứng dụng và server
• Các server được lưu trữ trong các file .exe, như ewsrv.exe là window server, hay efsrv.exe là file server. Để giảm chi phí chuyển đổi ngữ cảnh các server có cùng nhóm chức năng được dùng chung một tiến trình. Một server chính sẽ tạo tiến trình và các server khác sẽ thực thi tiểu trình của nó với tiểu trình của server chính.
• Ứng dụng console (không có giao diện đồ họa) được thực thi qua file chương trình .exe. Các ứng dụng dạng này phải tạo một console riêng để tương tác với người dùng.
• Các ứng dụng có giao diện đồ họa (GUI) là những thư viện polymorphic DLL với phần mở rộng là .app. Điểm vào của ứng dụng này là NewApplication() tạo và trả về một đối tượng dẫn xuất từ lớp CEikApplication (Series 80/9200Series/Series90) hay các lớp dẫn xuất từ CEikApplication phù hợp theo từng dòng điện thoại Symbian như CQikApplication (UIQ), CAknApplication (Series 60). Tiến trình ứng dụng được tạo bởi một chương trình nhỏ .exe, Apprun.exe, và tên của file chương trình ứng dụng .app được chuyển làm tham số cho Apprun.exe.

Định danh file

Symbian không quản lý các file dựa trên tên và phân biệt loại file dựa trên phần mở rộng như các hệ điều hành khác vẫn làm mà quản lý dựa trên một tổ hợp 3 số 32bit. Mỗi một số như vậy được gọi là định danh file (Unique Identifier-UID). UID được dùng để phân biệt và xác nhận, chọn lựa đúng các loại đối tượng khác nhau tại thời điểm nạp và thực thi, như phân biệt ứng dụng console, DLL, server, v.v...UID cũng là thành phần cơ bản để liên kết ứng dụng với tài liệu, ví dụ, tài liệu ứng với một ứng dụng sẽ yêu cầu hệ thống nạp ứng dụng khi tài liệu đó được mở.
3 UID này (UID1, UID2 và UID3) có giá trị hằng ứng với các tên gọi do Symbian quy định, nhưng cũng có thể sử dụng số hệ 10 hay hệ 16.
- UID1: định danh cấp hệ thống, chương trình thực thi .exe hay DLL được phân biệt nhờ UID1: với các giá trị tương ứng KExecutableImageUid=0x1000007A và KDynamicLibraryUid=0x10000079.
- UID2: định danh cấp giao tiếp, phân biệt các đối tượng cùng UID1, ví dụ UID2 được dùng để phân biệt thư viện dùng chung .dll và thư viện polymorphic (như .app, .mdl, .fep hay .ctl) qua các giá trị: KSharedLibraryUid=0x1000008d cho thư viện dùng chung và KUidApp=0x100039CE cho một ứng dụng đồ họa .app, recognizer(auto start)=0x10003A19, front-end procesors=0x10005E32, hay control panel=0x10003A34.
- UID3: định danh cấp chương trình thực thi, phân biệt các đối tượng có cùng UID2, chẳng hạn các ứng dụng đồ họa khác nhau sẽ có UID3 khác nhau. Do đó, có một tổ chức quản lý UID3 này cho toàn môi trường Symbian. Để có nó, lập trình viên phải gởi mail về uid@symbiandevnet.com để xin một số UID3 duy nhất trên môi trường Symbian.
Tổ hợp 3 số UID sẽ là duy nhất trên toàn môi trường Symbian. Nếu bạn sử dụng UID3 tùy tiện thì chương trình của bạn vẫn có thể chạy được nhưng nếu trên 1 máy nào đó có sẵn chương trình khác cùng loại và có cùng UID3 (nghĩa là trùng cả 3 số) thì chương trình của bạn sẽ không chạy vì chương trình cài trước đó sẽ được ưu tiên.

Một đối tượng hay một file trong Symbian có thể có một, hai, ba hay không cần UID.
- Để sử dụng thuận tiện trong việc tương tác và chuyển đổi dữ liệu với các hệ thống khác, hệ điều hành cho phép không cần sử dụng UID. Khi không có UID, Symbian sẽ phân biệt dựa vào quy ước đặt tên.
- Ứng dụng thực thi .exe thường chỉ có UID1 với giá trị KExecutableImageUid.
- Ứng dụng DLL: các ứng dụng này có UID1 là KDynamicLibraryUid. Với các thư viện dùng chung .dll, UID2 sẽ là KSharedLibraryUid. Với các thư viện polymorphic , UID2 sẽ có nhiều giá trị khác nhau tùy từng loại. UID3 thì các DLL hầu như không cần, chỉ có các loại thư viện polymorphic là cần đến.
- Đối với các loại tài liệu thì UID1 là KDirectFileStoreLayoutUid hoặc KPermanentFileStoreLayoutUid ứng với tài liệu độc lập và tài liệu cơ sở dữ liệu. UID2 và UID3 phụ thuộc ứng dụng mà tài liệu phục vụ.
Vì UID là giá trị được sử dụng để phân biệt nên cần sự chính xác. Đối với UID3 dùng trong ứng dụng đồ họa, trong quá trình phát triển, có thể sử dụng một giá trị bất kỳ trong khoảng 0x01000000 và 0x0fffffff. Nhưng khi cài ứng dụng vào điện thoại thì nhất định đó phải là con số được cấp chính xác và duy nhất.

Project file
Thông thường các project được xây dựng trên các IDE hỗ trợ nhưng trên Symbian thì khác. Vì có nhiều loại điện thoại, nhiều nền hệ thống và nhiều bộ công cụ phát triển khác nhau nên hệ điều hành Symbian đã cho phép project được đặc tả trong một định dạng độc lập. Sau đó, với các công cụ đi kèm trong các bộ công cụ phát triển hay trên các IDE hỗ trợ, các file project này được định dạng lại thành các file project phù hợp với IDE cho dòng điện thoại cụ thể và bộ SDK cho điện thoại đó.

1 File định nghĩa project (.mmp)
File này mô tả các thông tin của project. Đây là một file project độc lập, nó sẽ được chuyển thành file phù hợp môi trường phát triển cụ thể với các công cụ makmake hay lệnh abld.bat. Nó định nghĩa các file tài nguyên và file thông tin ứng dụng cần cho quá trình biên dịch. Cấu trúc file .mmp: gồm các dòng khai báo với các loại câu khai báo khác nhau. Thông thường chỉ một số ít khai báo được dùng. Sau đây là cú pháp các khai báo thông dụng qua ví dụ project HelloWorld với file HelloWorld.mmp:
• Aif: aif target-file source-path resource [color-depth] source-bitmap-list
Với:
+ target-file: tên file đích, thường viết luôn phần đuôi và nằm trong thư mục ứng dụng.
+ source-path: đường dẫn đến nơi chứa file tài nguyên mà aif cần
+ resource: tên các file tài nguyên mà aif cần với tên đầy đủ.
+ color-depth: đặc tả cho tất cả các file bitmap và ở dạng [c][digit] với c là color bitmap và "digit" thể hiện độ sâu.
aif helloworld.aif \helloworld\aif\ helloaif.rss c8 hello.bmp hellom.bmp
• Target: target filename.ext.
target HelloWorld.app
• TargetType: targettype target-type
Với target-type được hỗ trợ bao gồm: ani, app, ctl, dll, ecomiic, epocexe, exe, exedll, fsy, kdll, kext, klib, ldd, lib, mda, mdl, notifier, opx, pdd, pdl rdl, var, wlog.
targettype app
• UID: uid uid2 [uid3]
Mỗi ứng dụng thực thi có 3 loại UID, UID thứ nhất là targettype ở trên. Loại thứ hai và thứ ba là tùy chọn. UID được viết dưới dạng số hệ 10 hoặc hệ 16.
uid 0x100039CE 0x10004299
• TargetPath: targetpath target-path
targetpath \system\apps\HelloWorld
• SourcePath: sourcepath directory
Có thể có nhiều sourcepath nhưng đối với file mã và tài nguyên công cụ biên dịch chỉ quan tâm đến trong khai bao sourcepath **ối cùng.
sourcepath ..\group
• Source: source source-file-list
source HelloWorld_Main.cpp
• UserInclude: userinclude directory-list
userinclude ..\inc
• SystemInclude: systeminclude directory-list
systeminclude \epoc32\include
• Resource: resource resource-file-list (khai báo tên nên đầy đủ phần mở rộng)
resource HelloWorld.rss
• Library: library filename-list
library euser.lib apparc.lib cone.lib eikcore.lib

File HelloWorld.mmp hoàn chỉnh:

TARGET HelloWorld.app
TARGETTYPE app
UID 0x100039CE 0x10004299
TARGETPATH \system\apps\HelloWorld
SOURCEPATH .
SOURCE HelloWorld_Main.cpp
SOURCE HelloWorld_Application.cpp
SOURCE HelloWorld_Document.cpp
SOURCE HelloWorld_AppUi.cpp
SOURCE HelloWorld_AppView.cpp
USERINCLUDE .
SYSTEMINCLUDE \epoc32\include
RESOURCE HelloWorld.rss
LIBRARY euser.lib apparc.lib cone.lib eikcore.lib
AIF helloworld.aif \helloworld\aif\ helloaif.rss c8 hello.bmp hellom.bmp

2 File mô tả thành phần bld.inf
File này luôn luôn có tên là bld.inf. Nó liệt kê danh sách các file project (thường chỉ 1), file xuất, các nền hệ thống và các file xuất với phần kiểm tra. Nó được công cụ bldmake thực thi để tạo ra file bó abld.bat và các file thực thi khác. Thông thường chỉ có khai báo prj_mmpfiles cho các file project được sử dụng.
Ví dụ: Với project HelloWorld trên, file bld.inf có cấu trúc như sau:
// Project files
prj_mmpfiles
HelloWorld.mmp

Chú ý: - Mỗi câu khai báo xuất hiện trên một hàng riêng
- Sử dụng cách ghi chú của C++ cho phần ghi chú(// hoặc /* */)
- Các file nên khai báo đầy đủ phần mở rộng.
- Dấu \ được sử dụng để xác định sự liên tục dòng (dòng dưới cũng thuộc câu lệnh với dòng trên, do dài được cắt xuống), do đó khi khai báo đường dẫn, dấu \ sau cùng phải bỏ đi. Ví dụ nên viết SYSTEMINCLUDE \epoc32\include chứ không phải là SYSTEMINCLUDE \epoc32\include\.

Quy ước trong Symbian

Symbian đưa ra một số quy ước trong lập trình trên Symbian. Một số quy ước bạn không nhất thiết phải theo nhưng nhưng một số thì bạn nên tuân thủ để phục vụ cho việc lập trình của bạn thuận lợi, tránh sai sót và dễ nâng cấp sau này.

1. Tên lớp:
Symbian sử dụng các quy ước đặt tên sau để xác định đặc tính cơ bản của một lớp:
• Lớp T: lớp đơn giản (tựa như typedef) thường xây dựng từ các kiểu dữ liệu cơ sở hay kết hợp chúng lại, có thể so sánh lớp T với struct đơn giản bao gồm các dữ liệu public. Nó không có destructor (có thể có constructor nhưng hiếm) và thường được lưu trên stack, có thể lưu trên heap. Kiểu liệt kê (enum) cũng thường khai báo dưới dạng lớp T. Ví dụ: TInt, TBool, TPoint, TDes, TMonthsOfYear ...
• Lớp C: Lớp có constructor và destructor và tất cả đều là dẫn xuất từ CBase. Các đối tượng của chúng được tạo bằng new và luôn được lưu trữ trên heap. Ví dụ: CConsoleBase, CActive,...
• Lớp R: Lớp R (đại diện cho Resource), thường đại diện cho một loại tài nguyên, quản lý một sesion kết nối với một server phục vụ một tài nguyên. Đối tượng lớp R thường có một hàm khởi tạo (Open() hoặc Create() hay Initialize()) và một hàm kết thúc (Close() hay Reset()) để giải phóng tài nguyên. Quên gọi hàm kết thúc khi dùng đối tượng lớp R là một lỗi thường gặp và kết quả là sẽ bị lủng bộ nhớ. Nó có thể được lưu trên heap, nhưng thường là trên stack. Ví dụ: RFile, RTimer, RWindow,...
• Lớp M (Mix-ins): Lớp ảo (abstract) giống như interface trong Java, nó chỉ bao gồm các phương thức ảo rỗng và không có dữ liệu cũng như constructor. Việc kế thừa nhiều lớp trong Symbian là cho phép tuy nhiên phải theo quy tắc là kế thừa chính từ 1 lớp C (bắt buộcphải có và viết đầu tiên) và nhiều lớp M. Ví dụ: MGraphicsDeviceMap, MGameViewCmdHandler,...
Việc phân biệt giữa T, C và R lớp là rất quan trọng, nó ảnh hưởng tới việc giải phóng bộ nhớ khi sử dụng cũng như cách thức xử lý các đối tượng thuộc các lớp này.
Ngoài ra trong Symbian còn có các lớp tĩnh (static) phục vụ cho một số chức năng riêng như lớp User hay lớp Mem. Một ngoại lệ khác là lớp HBufC, chúng ta sẽ nói đến no ssau trong phần desciptor

2 Tên dữ liệu
Tương tự, Symbian cũng dùng chữ cái đầu để phân biệt các loại dữ liệu:
• Hằng liệt kê (Enumerated constant): Bắt đầu với ký tự E, nó đại diện cho một giá trị hằng trong một dãy liệt kê. Nó có thể là một phần của lớp T. Ví dụ: (ETrue, EFalse) của TBool hay EMonday là một thành phần của TDayOfWeek.
• Hằng (constant): Bắt đầu với ký tự K, thường được dùng trong các khai báo #define hay các giá trị hằng do Symbian quy định. Ví dụ: KMaxFileName hay KErrNone.
• Biến thành phần (member variable): Bắt đầu với chữ cái i (instance), được dùng khi sử dụng các biến động là thành viên của một lớp. Đây là quy ước quan trọng, dùng cho việc hủy vùng nhớ trên heap của các đối tượng này trong destructor. Tôi thường chỉ dùng quy ước này nếu biến này sẽ được lưu trên heap, còn trên stack thì không. Ví dụ: iDevice, iX, …
• Tham số (argument): Bắt đầu bằng chữ a (argument), được dùng khi các biến làm tham số. Ví dụ: aDevice, aX, …
• Macro: Không có quy ước đặc biệt. Tất cả đều viết hoa và dùng dấu gạch dưới để phân tách từ. Ví dụ: IMPORT_C, _TEST_INVARIANT, _ASSERT_ALWAYS, v.v…
• Biến cục bộ (automatic): chữ cái đầu nên viết thường. Biến toàn cục (global): nên viết hoa chữ cái đầu nhưng để tránh nhầm lẫn nên bắt đầu tên bằng chữ cái “g”. Tuy nhiên trên Symbian không khuyến khích dùng biến toàn cục.

3 Tên hàm
Tên hàm bắt đầu bằng ký tự hoa. Khác với 2 trường hợp trên, quy ước đặt tên hàm lại dựa trên ký tự cuối cùng:
• Hàm không ngắt giữa chừng (non-leaving function): đó là hàm mà trong quá trình thực thi nó đều diễn ra suông sẻ, chi tiết tôi sẽ nói sau. Ví dụ: Draw() hay Intersects().
• Hàm ngắt giữa chừng (leaving function): là hàm bị ngắt ngang vì một lý do nào đó: lỗi,, thiếu tài nguyên, ... Hàm này kết thúc bằng ký tự L. Ví dụ: DrawL() hay RunL().
• Hàm LC: Kết thúc với cặp ký tự LC. Các hàm này trong lòng nó có khai báo một đối tượng mới, và có đặt đối tượng này lên cleanup stack (ngăn xếp chứa các đối tượng cần xóa khi có ngắt xảy ra, sẽ nói rõ sau) và có khả năng xuất hiện ngắt trong khối xử lý hàm. Bạn lưu ý là sau khi gọi hàm này sẽ phải gọi Cleanup:opAnd Destroy(), lý do tôi sẽ nói trong phần về cleanup stack, nếu quên gọi nó chắc chắn bạn sẽ bị lỗi 3 mà không hiểu tại sao. Ví dụ: AllocLC(), CreateLC(), OpenLC() hay NewLC(),...
• Các hàm Get và Set: trong trường hợp đơn giản thường là các hàm thành viên của một lớp. Set dùng cho việc xác lập giá trị cho một biến thành viên của lớp. Get được dùng cho các hàm sẽ trả về giá trị trên tham số. Khi hàm có giá trị trả về thì thường không dùng Get.
Ví dụ: SetThing(aData); GetThing(aData); nhưng iData = Thing();

4 Cấu trúc thư mục project
Tuy không bắt buộc nhưng Symbian khuyến khích lập trình viên xây dựng thư mục project ứng dụng thành các thư mục con với chức năng riêng biệt. Thông thường thư mục project có cấu trúc như sau:
• Thư mục project: chứa các file project .mmp, bld.inf, file tài nguyên .rss. Thư mục này cũng sẽ lưu trữ các file thông tin cụ thể cho chương trình dùng với các IDE. Thư mục này thường được đặt tên là: group.
• Thư mục các file khai báo: chứa các file khai báo cho file tài nguyên và các file mã nguồn. Thư mục này thường có tên là: inc.
• Thư mục mã nguồn: chứa các file cài đặt các lớp chương trình. Thư mục này thường có tên là: src.
• Thư mục dữ liệu: chứa dữ liệu cần cho chương trình ứng dụng và có tên là data.
• Thư mục thông tin ứng dụng: chứa file tài nguyên .rss để tạo file .aif và các hình ảnh, tài nguyên phục vụ cho ứng dụng. Tậo hợp các hình này được lưu trữ trong một file .mbm (multi bitmap). Thư mục này có tên là aif.
• Thư mục cài đặt: chứa các file .pkg, các thành phần cài đặt bổ sung cho ứng dụng. Thư mục này thường có tên là: install.
• Thư mục chương trình: lưu trữ file cài đặt .sis. Thường nó được gộp với thư mục install. Thư mục này có tên là release.
Tuy nhiên các project thường chỉ gồm các thư mục: group, inc và src.

5. Trình bày code:
Nếu lập trình trên C và Java thấy 2 phong cách trình bày quen thuộc là:
void Example()
{
.........
.........
}


void Example(){
.........
.........
}

thì Symbian đề xuất cách trình bày sau:
void Example()
->{
->.........
->........
->}
Bạn không nhất thiết phải theo cách này. Ban đầu tôi cũng thấy khó chịu nhưng sau một thời gian sử dụng, thấy nó mang lại một phong cách trình bày sáng sủa và dễ đọc hơn.

Cấu trúc ứng dụng Symbian

Ứng dụng đồ họa là loại chương trình chúng ta hay viết nhất và cũng là loại thực thi chủ đạo trên Symbian.

1 Phân loại
Trên Symbian, ứng dụng đồ họa được chia thành ứng dụng hướng file (file-based application) như Word hay Contact, Agenda và ứng dụng khác (non file-based application) như Calculator, các trò chơi.
• Ứng dụng file là ứng dụng phục vụ cho việc lưu trữ các thông tin, tài liệu dưới dạng các file có cấu trúc riêng. Trên Symbian, ứng dụng file lại được chia làm 2 loại khác nhau:
- Ứng dụng file tài liệu độc lập: là các ứng dụng file mà có thể nạp và lưu trữ tài liệu dưới dạng các file độc lập như Word hay Record. Khi một file tài liệu được nạp, toàn bộ dữ liệu file sẽ được lưu và xử lý trong RAM và khi lưu file xuống lại đĩa thì file cũ sẽ bị xóa và được thay thế bằng file mới. Đối với các ứng dụng file dạng này, dữ liệu thật xem như ở trên RAM, các file chỉ lưu lại các phiên bản khác nhau của tài liệu ứng dụng. Các file tài liệu này có biểu tượng của ứng dụng và chúng có chứa UID của ứng dụng. Đây là cơ sở để xác định tài liệu thuộc ứng dụng nào, chúng không dựa trên phần mở rộng của tên như trên các hệ điều hành khác. Một số file tài liệu dạng này có thể cho phép nhúng một tài liệu của một ứng dụng khác, biến tài liệu tồn tại độc lập này thành một phần tài liệu của nó. Ví dụ: tài liệu hình ảnh có thể nhúng vào một tài liệu danh bạ Contact.
- Ứng dụng file cơ sở dữ liệu: là các ứng dụng file nhưng tài liệu của nó là các file cơ sở dữ liệu như trong ứng dụng Agenda. Tại mỗi thời điểm sử dụng, chúng ta chỉ nạp và lưu các mẫu tin (record) có cấu trúc trên cơ sở dữ liệu qua việc sử dụng các đầu vào tương ứng nhờ các chỉ mục. Đối với các ứng dụng file này, dữ liệu thật lại nằm trên đĩa trong các file cơ sở dữ liệu, còn trên RAM chỉ là các đoạn dữ liệu sao chép từ file cơ sở dữ liệu.

2 Cấu trúc ứng dụng đồ họa
Cấu trúc ứng dụng đồ họa Symbian cũng gồm có 4 lớp:
• Lớp ứng dụng (application): lớp ứng dụng định nghĩa các thuộc tính ứng dụng, và tạo ra các tài liệu mới cho ứng dụng. Trong trường hợp đơn giản nhất, nó chỉ bao gồm định danh ứng dụng UID.
• Lớp tài liệu (document): đại diện cho mô hình dữ liệu của ứng dụng. Nếu ứng dụng là ứng dụng file, các ứng dụng phục vụ chính cho việc tạo các file tài liệu, lớp này sẽ đảm nhận việc nạp và lưu trữ các file tài liệu cho ứng dụng. Với các ứng dụng không phải là ứng dụng file, lớp tài liệu vẫn tồn tại với mục đích để nạp phần giao diện ứng dụng.
• Lớp giao diện ứng dụng (AppUI – application user interface): Nhiệm vụ chính của lớp này là cung cấp sự tương tác giữa ứng dụng với người dùng qua các đối tượng điều khiển như toolbar hay menu qua hàm HandleCommandL() đồng thời tạo các view, phần giao tiếp chính giữa ứng dụng và người dùng.
• Lớp hiển thị (AppView): đây thực chất là một control, mục đích chính của nó là thể hiện các dữ liệu của ứng dụng lên màn hình và cho phép người dùng tương tác với nó. Nó cung cấp các chức năng quản lý sự kiện nhập như bàn phím (OfferKeyEventL()) và con trỏ (HandlePointerEventL()).

Đây là 4 lớp rất cơ bản mà ứng dụng nào cũng phải có.
Tuy nhiên nếu chỉ với 4 lớp trên thì chương trình ứng dụng không thể thực thi được. Như đã biết thì ứng dụng đồ họa là một loại polymorphic DLL, nó được thực thi nhờ chương trình apprrun.exe. Do đó trong mỗi ứng dụng đồ họa Symbian phải có thêm các hàm đảm nhận việc khởi tạo hoạt động cho ứng dụng đồ họa. Khi ứng dụng được chọn thực thi, chương trình apprun.exe sẽ hoạt động với tên ứng dụng và tên file ứng dụng làm tham số. Chương trình apprun sẽ sử dụng kiến trúc ứng dụng APPARC để nạp ứng dụng qua việc kiểm tra UID2 là KUiApp (0x100039ce) và tạo đối tượng ứng dụng đồ họa qua hàm NewApplication(). Các hàm này bao gồm hàm NewApplication() và hàm E32Dll(TdllReason) (một hàm chỉ cài đặt, không sử dụng). Từ khóa EXPORT_C để báo hàm NewApplication là đầu vào của một DLL.
EXPORT_C CApaApplication* NewApplication()
{
return new CExampleApplication;
}
GLDEF_C TInt E32Dll(TDllReason)
{
return KErrNone;
}

Nhân đây tôi cũng xin nói về cấu trúc thư viện dùng chung (.dll). Như chúng ta đã biết, chúng có nhiều đầu vào khác nhau nhằm mục đích cung cấp nhiều hàm cho các ứng dụng đồ họa hay các dll khác sử dụng. Do đó cấu trúc của nó như sau: trong file header .h, những hàm bạn dự định cung cấp cho các chương trình khác dùng thì khai báo bắt đầu bằng từ khóa IMPORT, ngược lại trong file cài đặt .cpp thì bạn sẽ khai báo từ khóa EXPORT ở đầu các hàm này. Sau khi biên dịch, file .lib sẽ được các chương trình nào muốn xài thêm vào trong danh sách thư viện của nó còn file .dll được các ứng dụng cài đặt kèm để thực thi các hàm cần thiết.

Tiếp theo tôi sẽ giới thiệu mô hình thiết kế được lựa chọn là mô hình thiết kế chủ đạo trong Symbian: mô hình MVC (Model View Control)


Mô hình thiết kế MVC

Các ứng dụng đồ họa thường được phát triển theo nguyên tắc sau: những gì thể hiện trên màn hình giao tiếp với người dùng sẽ do các hàm vẽ (draw) đảm nhận. Chúng chỉ có nhiệm vụ đơn giản là vẽ lại dữ liệu của ứng dụng lên màn hình, chúng không thay đổi dữ liệu. Nếu bạn muốn thay đổi gì đó thì bạn phải sử dụng hàm khác và rồi gọi lại hàm vẽ này để vẽ lại dữ liệu đã thay đổi.
Nguyên tắc này thật ra là một mô hình thiết kế (design pattern) rất phổ biến: mô hình model-view-controller, thường viết tắt là mô hình MVC.
- Model: dữ liệu của ứng dụng, nó đảm nhận việc lưu trữ các thông tin dữ liệu của ứng dụng.
- View: nơi thể hiện dữ liệu của ứng dụng, người dùng chỉ có thể biết ứng dụng thông qua nó.
- Controller: phần này có nhiệm vụ thao tác trên dữ liệu ứng dụng: cập nhật model sau đó yêu cầu view thể hiện lại phần cập nhật.
Tuy nhiên không phải lúc nào cũng phải đầy đủ cả phần này. Tùy theo tính chất của ứng dụng mà có thể ranh giới giữa model và view không rõ ràng hay có thể thiếu đi phần controller.
Có lẽ bây giờ chắc bạn nghĩ vậy thì mô hình này có liên quan gì đến lập trình C++ trên Symbian?
Mô hình MVC và Symbian có mối quan hệ rất mật thiết. Như tôi nói trong phần cuối bài trước, MVC là mô hình thiết kế chủ đạo trong Symbian. Nếu để ý kỹ bạn sẽ thấy lớp document là hiện thân của model, lớp AppView chính là view còn AppUi sẽ đóng vai trò là controller trong mô hình MVC. Với những ứng dụng phức tạp thì sẽ có nhiều lớp đảm nhận một thành phần trong MVC.
Không những vậy, hầu hết các control trong Symbian đều được thiết kế theo mô hình MVC. Nắm bắt được điều này, bạn sẽ dễ dàng thao tác với các control trong Symbian. Tôi nhớ là có khá nhiều người mới lập trình Symbian khi làm quen với listbox đều đặt câu hỏi: làm sao để lấy dữ liệu một item trong listbox đây bởi trong lớp CEikListbox không thể tìm thấy hàm nào đảm nhận việc này. Đó là vì listbox trong Symbian cũng được thiết kế theo mô hình MVC nên nếu muốn lấy dữ liệu, bạn phải đến lớp MListBoxModel thông qua hàm Model() trong lớp CEikListbox.

To bggroup: Trong bộ cài SDK UIQ 2.1 có một phần rất quan trọng là Perl mà bạn đã quên chọn lúc cài đặt. Perl được dùng để chạy các tool cho Symbian như biên dịch, tạo sis hay các tool tiện ích khác. Nếu thiếu Perl bạn sẽ không làm được gì cả. Nên chọn phần perl trong bộ SDK thay vì lên trang perl mà nickyboy chỉ bởi lẽ có thể phiên bản perl bạn down về không phù hợp. Một điểm lưu ý là SDK Series60 v2.0 thiếu phần cài đặt perl.

Reflink: http://my.opera.com/nhadautu/blog/2008/01/06/chuong-trinh-hoat-dong-tren-symbian