Monday, February 6, 2017

how to fix error "Could not open /dev/vmmon: No such file or directory" (vmware fusion, mac sierra)

After install virtualbox 5.0 to my macbook, i cannot start up any virtual machine, vmware fusion error display : "Could not open /dev/vmmon: No such file or directory". I'm tried delete virtualbox in /Applications but not success. But i found we can fix it by  run file "VirtualBox_Uninstall.tool" (file in same directory with virtualbox install file) to remove virtualbox. Now, all virtual machine on my computer working fine.

Tuesday, October 4, 2016

Code injections (Win32API) note

1. _ http://www.rohitab.com/discuss/topic/39535-code-injections-beginner-and-advanced/
2._ http://www.codeproject.com/Articles/4610/Three-Ways-to-Inject-Your-Code-into-Another-Proces

Friday, September 23, 2016

How to install Keypatch plugin for IDA 6.8 (step by step)

In this tutorial, i will show you how to install Keypatch plugin for IDA 6.8.
First, you need download 4 files : Windows - Core engine, Python module for Windows - Binaries , Visual C++ Redistributable Packages for Visual Studio 2013  (32bit or 64bit depend on your OS architecture) and Keypatch
Step 1. Install Visual C++ Redistributable Packages for Visual Studio 2013  and  Python module for Windows - Binaries 
Step 2. Extract Windows- Core engine and  Keypatch files, you will see keystone.dll file in keystone-0.9.1-win32 folder and keypatch.py in Keypatch folder.

Step 3. Copy keystone.dll to C:\Python27\Lib\site-packages\keystone
Step 4. Copy keypatch.py to your IDA plugins directory (ex: C:\Program Files\IDA 6.8\plugins on my PC)
Step 5. Restart IDA. Done.

How to install Keypatch plugin for IDA 6.8 (step by step)

In this tutorial, i will show you how to install Keypatch plugin for IDA 6.8.
First, you need download 4 files : Windows - Core engine, Python module for Windows - Binaries , Visual C++ Redistributable Packages for Visual Studio 2013  (32bit or 64bit depend on your OS architecture) and Keypatch
Step 1. Install Visual C++ Redistributable Packages for Visual Studio 2013  and  Python module for Windows - Binaries 
Step 2. Extract Windows- Core engine and  Keypatch files, you will see keystone.dll file in keystone-0.9.1-win32 folder and keypatch.py in Keypatch folder.

Step 3. Copy keystone.dll to C:\Python27\Lib\site-packages\keystone
Step 4. Copy keypatch.py to your IDA plugins directory (ex: C:\Program Files\IDA 6.8\plugins on my PC)
Step 5. Restart IDA. Done.

Saturday, January 30, 2016

MatesCTF (tháng 01/2016) re300 writeup


Binary không khó, tìm ra trick debug + suy luận thuật toán tí (vài tiếng đối với mình) là ra. LOL :3
Binary khá "dị", compiler = Borland C++, đuôi .exe nhưng load vào ollydbg fail, load vào IDA thì được nhưng tất nhiên là không F5 được. Gúc một lúc thì biết đây là file 16bit windows và chạy thông qua ntvdm.exe (olly, IDA không hỗ trợ debug trực tiếp file 16bit, nguyên nhân hồi sau sẽ rõ. Ntvdm là 1 file đặc biệt của windows, nó cho phép chạy file 16bit windows trên windows 32, 64bit - ntvdm có thể coi là 1 dạng máy ảo dos). _https://en.wikipedia.org/wiki/Virtual_DOS_machine#Windows_NTVDM
Vì thế, nếu bấm trực tiếp vào binary sẽ thấy hiện lên thêm tiến trình của ntvdm.exe
Có nhiều cách để debug file này, có thể dùng ida, olly attack vô ntvdm.exe (mình chưa làm cách này, nhưng m nghĩ là được), hoặc tìm 1 debugger cho phép disassembly và debug trực tiếp (cách mình làm). Công cụ mình sử dụng là _openwatcom.org
Sau khi download về mò mẫm 1 hồi tìm được cách debug file dạng này. File cần tìm \binw\wd.exe.
Chạy file đó, chỉnh open binary (có thể có một vài lỗi lằng nhằng ở bước này như không support fullscreen, mất chuột khi chạy trên win7, win8,....). Màn hình debug gần giống windbg, coi được register, flag, disassembly,....
Trick vậy là xong, tiến hành debug 1 hồi thì đến thuật toán check key:
- ký tự nằm từ 0-9, A-Z 
- key nhập vào gồm 24 ký tự sau đó được chia làm 6 block, tạm gọi từ a1-a6 (4 char/block). Ví dụ nhập vào 12345678....  thì a1= 1234, a2 = 5678 (mỗi block được xử lý thành 1 word)
- với mỗi block (ví dụ a1= ABCD), sẽ có thêm 1 giá trị đi kèm (mình gọi là sig). Nếu a1 > 0x7fff thì sig_a1 = 0xffff, ngược lại sig_a1 = 0. Hình dưới là phần thuật toán check key chính:
Thuật toán check key được mô tả như sau:
1.a6 -a1 = 0xa2ff 
2.sig_a6  - (sig_a1+carry_flag) ==0  
3.a1 - a2 = 912 tuong tu
4.sig_a1 - (sig_a2+carry_flag) ==0 
5.a2 - a3 = 5b6a             
6.sig_a2 - (sig_a3+carry_flag) == 0xffff
7.a3-a4 = b5f0  
8.sig_a3 - (sig_a4 + carry_flag) ==0
9.a4 -a5 = 3a4b
10.sig_a4 - (sig_a5 + carry_flag) ==-1
11.a6+a5 = bca0
12.sig_a6 + sig_a5 + carry_flag ==0

Tính toán, suy luận, quay cóp cẩn thận ta sẽ tính ra được
a1,a2,a4 > 0x7fff. a3, a5,a6 < 0x7fff (bước này nếu không để ý cộng luôn biểu thức 1, 3,5,7,9,11 rồi tính được a6 trước là sai luôn).
Final:
maxA = 0x7fff
for a6 in xrange(0,maxA+1):
a5 = 0xbca0 - a6
a1 = 0xffff- (0xa2ff-a6 - 1)
a2 = a1 -0x912
if a2 > 0x7fff:
a3 = a2 - 0x5b6a
a4 = 0xffff-(0xb5f0-a3-1)
if a4 > 0x7fff:
tmp = a4-0x3a4b
if tmp ==a5:
print hex(a1),hex(a2),hex(a3),hex(a4),hex(a5),hex(a6)

Tìm được a1,...a6, nhập lại theo thứ tự và lượm flag. :v 




Saturday, August 8, 2015

[WhiteHat contest 10] Re400 writeup

Trap, trap everywhere.....
Thực sự đối với bài này mình cũng không biết nên đánh giá khó hay dễ. Dễ vì thực ra thuật toán check flag 'thực sự' rất đơn giản (chỉ vài dòng code là ra). Khó vì nếu đi sai 1 hướng thì sẽ mất rất nhiều thời gian để thoát ra khỏi mớ bòng bong. Do đi sai đường nên mình phải mất tới 2 ngày mới solved được nó.
Bài này sử dụng khá nhiều kỹ thuật anti debug và nên dùng song song cả ida và ollydbg 2 để debug. (Vì sao lại là ollydbg2 mà không phải là v1 mình sẽ nói ở bên dưới). Đồng thời do bài này nếu giải thích kỹ sẽ rất dài nên một số đoạn mình sẽ bỏ qua (thực ra là do lười writeup kỹ). :D. Chỉ tập chung chính vào cách check key của bài này.
Lòng vòng nhiều quá, bắt đầu nào.
Load vào IDA, ngay ở đoạn đầu tiên của hàm main:
if ( argc > 0 && !_stricmp("Reverse", *argv) )
  {
    sub_D31A90();
    return 0;
  }
 Mục đích của đoạn này là sẽ chạy sub_D31A90() nếu tên tham số argv = "Reverse". Khi chạy một file thì tham số truyền vào argv sẽ là đường dẫn đến file đó, trong khi argv ở đây lại không có đường dẫn? Có 1 cách để làm việc này, ở ngay đoạn tiếp theo
if ( !sub_D31870() )
  {
    if ( !CreateProcessA(&Filename, "Reverse", 0, 0, 0, 0, 0, 0, &StartupInfo, &ProcessInformation) )
      printf("CreatePrcess Error");
    v5 = 0;
    do
    {
      byte_D41044[v5] ^= 0x11u;
      ++v5;
    }
 Bỏ qua sub_D31870() đoạn này chỉ nhằm mục đích xem file đã đang chạy hay chưa.
CreateProcessA(&Filename, "Reverse", 0, 0, 0, 0, 0, 0, &StartupInfo, &ProcessInformation) 
Hàm này sẽ sinh ra một process mới,argv = "Reverse".  Và tất nhiên process này sẽ run
sub_D31A90(); Check sâu vào trong hàm này, khá dài dòng nhưng mục đích chính là process mới tạo ra sẽ lắng nghe trên cổng 8888 localhost, sau khi nhận được dữ liệu sẽ tiến hành check. Để capture các gói tin loopback bạn có thể dùng công cụ Rawcap.
Antidebug: Trong hàm này thực hiện 2 kỹ thuật antidebug: GetTickCount và CheckRemoteDebuggerPresent (các bạn hãy hỏi anh gồ để biết thêm thông tin về 2 kỹ thuật này, riêng đối với CheckRemoteDebuggerPresent thì chỉ có tác dụng khi sử dụng win XP).
Khi debug file này bằng IDA và ollydbg1 sẽ không quan sát và debug được process con mới tạo ra, ollydbg2 thì đã hỗ trợ sẵn (Vào options-> debugging->events, check chọn Debug child process). Sau hàm createprocessA một cửa sổ ollydbg mới sẽ xuất hiện
Trở về với process chính của chương trình:
scanf("%500[^\n]s", byte_D41B90);
 if ( v6 >= 7 && !strncmp(byte_D41B90, "FLAG{", 5u) && byte_D41B8F[v6] == '}' )
    {
      memcpy(&byte_D41D88, &unk_D41B95, v6 - 6);
      if ( strlen(&byte_D41D88) <= 40 )

     {
         v8 = sub_D31470();
-> Nhập vào key với định dạng: FLAG{xxxx....}, len <=40, chỉ copy nguyên 'xxxx...' (mình tạm gọi là S) vào byte_D41D88, nếu đúng định dạng thì sẽ chạy tiếp func sub_D31470() để kiểm tra. Func này mục đích là kiểm tra các ký tự bên trong cặp {} phải nằm từ [0-9], và [A-F] [a-f]
if ( v9 == (strlen(&byte_D41D88) >> 1) - 1 && *(dword_D41B54 + v9) != '_' )
S được chia thành từng cặp 2 ký tự. Cặp ký tự cuối của S =5F
if ( v10 == 2596 )
dword_D41B50 = sub_D31960();
 v13 = CreateThread(0, 0, StartAddress, 0, 0, 0);

WaitForSingleObject(v13, 0xFFFFFFFF);
Ví dụ S = 011F -> v10 = 0x01 + 0x1F
sub_D31960(): Từ cặp trong S sẽ được xor với len(S)/2
 v13 = CreateThread(0, 0, StartAddress, 0, 0, 0);
-> Trong StartAddress chứa 2 kỹ thuật antidebug nữa, mời các bạn đọc thêm phần openprocess và Parent processes ở đây
if ( _stricmp(&byte_D41D88, "Whitehat_Contest_Is_Amazing") && sub_D31700() )
Trap1 -> đoạn này không có tác dụng gì, chỉ có mục đích đánh lừa
if ( dword_D42174 != dword_D41F7C && sub_D31730(strlen(&byte_D41D88)) )
Trap2 -> khi không bị debug thì dword_D42174 == dword_D41F7C và việc kiểm tra sub_D31730 là vô nghĩa
 CreateThread(0, 0, sub_D319A0, &Parameter, 0, 0);
Tạo ra một thread mới, đầu vào chính là S (sau khi đã xor )
Sub_D319A0:
 v1 = lpThreadParameter;
  operator new(8u);
  WSAStartup(0x202u, &WSAData);
  v2 = socket(2, 1, 6);
  name.sa_family = 2;
  *&name.sa_data[2] = inet_addr("127.0.0.1");
  *&name.sa_data[0] = htons(0x22B8u);
  if ( connect(v2, &name, 16) )
  {
    do
    {
      Sleep(0x1388u);
      connect(v2, &name, 16);
    }
    while ( connect(v2, &name, 16) );
    v1 = lpThreadParameter;
  }
  send(v2, *v1, *(v1 + 1), 0);
Connect tới cổng 8888 của localhost và send S lên đó.
Process được tạo ra ngay đầu tiên sẽ xử lý S. Khá dài dòng và khá nhiều trap nữa (với mục đích giả vờ check key).
Tương tự tại process chính cũng có khá nhiều đoạn giả check key (xuất hiện các string giả).
When you have eliminated the impossible whatever remains, however improbable, must be the truth. - Shelock Homes.
Và cuối cùng đây là thuật toán tạo key.
final =[0x41,0x17,0x25,0xC7,0xCB,0x55,0x5F,0x9B,0xC7,0x7C,0xC2,0xD6,0x7C,0x12,0xAF,0x80]
key =[0]*16
key[15] = 0x4F
flag ="FLAG{"
for i in xrange(len(key)-2,-1,-1):
    key[i] = final[i] ^ key[i+1]
key = list(map((lambda x:x^0x10),key))
for i in key:
    flag +=hex(i)[2:]
flag += "}"
print flag.upper()