2015-03-16

LZMA compressed SWF file vs 7z LZMA file

Lần này có việc phải decompress SWF file dùng LZMA, nên note lại cho nhớ.
Nếu sử dụng Python thì nên cài pylzma xong xài script tại đây
https://github.com/OpenGG/swfzip
Cần thiết thì chỉnh 1 chút xíu là dùng được.

Nếu muốn viết tool thay vì chạy script thì có thể dùng library của 7z. Về header của 2 loại file sẽ khác nhau chút đỉnh, nên khi dùng library 7z sẽ không decompress được file ZWS.

Chi tiết nó có ghi ở đây nhưng khá là khó xem (Adobe Flash)

Issue


When you decompress an LZMA-compressed SWF file using the ByteArray.uncompress method, an exception is thrown.

Solution


The LZMA header format Flash authoring uses does not match the header 7z format uses. You can convert the SWF file in the LZMA format into the 7z LZMA format by updating the header.
https://helpx.adobe.com/flash-player/kb/exception-thrown-you-decompress-lzma-compressed.html

Mình sẽ note lại cho kỹ header 2 thằng này như sau, cần phải điều chỉnh lại thông tin trước khi thực hiện decompress với 7z.

//-----------------------------------------------------------------
// SWF file LZMA header
//-----------------------------------------------------------------
// bytes 0-3: ZWS+version 
// bytes 4-7: Uncompressed length, the uncompressed length of the SWF data 
// (includes ZWS+version (4 bytes) and uncompressed length (4 bytes)) 
// bytes 8-11: Compressed length 
//      Compressed length does not include header (4+4+4 bytes) or lzma props (5 bytes)
//      Compressed length does include LZMA end marker (6 bytes)
// bytes 12-16: LZMAproperties 
// bytes 17-n: Compressed data
//
// 17 bytes = 12 bytes header + 5 bytes LZMA properties
//-----------------------------------------------------------------

//-----------------------------------------------------------------
// 7z LZMA header
//-----------------------------------------------------------------
// bytes 0-4: LZMA properties 
// bytes 5-12: Uncompressed length (take the 
// swf lzma length - 8 (don't include ZWS+version + uncompressed length))
// bytes 13-n: Compressed data            
//
// 13 bytes  = 8 bytes uncompressed length + 5 bytes LZMA properties
//-----------------------------------------------------------------

SevenZip.Compression.LZMA.Decoder coder = new SevenZip.Compression.LZMA.Decoder();

// Read the decoder properties (bytes 12-16)
byte[] properties = swfBytes.Skip(12).Take(5).ToArray();
// Calculate uncompressed length (bytes 4-7), subtract 8 (remove header bytes) long len = Le2Int(swfBytes, 4) - 8; coder.SetDecoderProperties(properties); byte[] decompressedData; using (Stream input = new MemoryStream(swfBytes.Skip(17).ToArray())) using (MemoryStream output = new MemoryStream()) { coder.Code(input, output, input.Length, len, null); decompressedData = output.ToArray(); }




Đoạn code chuyển từ int sang bytes, little endian

int Le2Int(byte[] data, int offset = 0)
{
    return (data[offset + 3] << 24)
            | (data[offset + 2] << 16)
            | (data[offset + 1] << 8)
            | data[offset];
}

byte[] Int2Le(int data)
{
    byte[] bytes = new byte[4];
    bytes[0] = (byte)data;
    bytes[1] = (byte)(((uint)data >> 8) & 0xFF);
    bytes[2] = (byte)(((uint)data >> 16) & 0xFF);
    bytes[3] = (byte)(((uint)data >> 24) & 0xFF);
    return bytes;
}
Với Python, unzip các file trong folder. Nếu unzip file xem trong swfzip


#!/usr/bin/python
#
# This script is inspired by jspiro's swf2lzma repo: https://github.com/jspiro/swf2lzma
#
#
# SWF Formats:
## ZWS(LZMA)
## | 4 bytes       | 4 bytes    | 4 bytes       | 5 bytes    | n bytes    | 6 bytes         |
## | 'ZWS'+version | scriptLen  | compressedLen | LZMA props | LZMA data  | LZMA end marker |
##
## scriptLen is the uncompressed length of the SWF data. Includes 4 bytes SWF header and
## 4 bytes for scriptLen itself
##
## compressedLen does not include header (4+4+4 bytes) or lzma props (5 bytes)
## compressedLen does include LZMA end marker (6 bytes)
#
import os
import pylzma
import sys
import struct
import zlib
import shutil

def check(test, msg):
    test or exit("Error: \n" + msg)
    
def debug(msg, level = "info"):
    print '%s : %s' %(level, msg)

def confirm(prompt, resp = False):
    """prompts for yes or no response from the user. Returns True for yes and
    False for no.

    'resp' should be set to the default value assumed by the caller when
    user simply types ENTER.

    >>> confirm(prompt='Create Directory?', resp=True)
    Create Directory? [y]|n:
    True
    >>> confirm(prompt='Create Directory?', resp=False)
    Create Directory? [n]|y:
    False
    >>> confirm(prompt='Create Directory?', resp=False)
    Create Directory? [n]|y: y
    True

    """

    if prompt is None:
        raise Exception('Not valid prompt')

    if resp:
        prompt = '%s %s/%s: ' % (prompt, 'Y', 'n')
    else:
        prompt = '%s %s/%s: ' % (prompt, 'N', 'y')

    while True:
        ans = raw_input(prompt)
        print ''
        if not ans:
            return resp
        if ans not in ['y', 'Y', 'n', 'N']:
            print 'please enter y or n.'
            continue
        if ans == 'y' or ans == 'Y':
            return True
        if ans == 'n' or ans == 'N':
            return False

def unzip(inData):
    if inData[0] == 'C':
        # zlib SWF
        debug('zlib compressed swf detected.')
        decompressData = zlib.decompress(inData[8:])
    elif inData[0] == 'Z':
        # lzma SWF
        debug('lzma compressed swf detected.')
        decompressData = pylzma.decompress(inData[12:])
    elif inData[0] == 'F':
        # uncompressed SWF
        debug('Uncompressed swf detected.')
        decompressData = inData[8:]
    else:
        #exit('not a SWF file')
        decompressData = []
        return decompressData

    sigSize = struct.unpack("<I", inData[4:8])[0]
    debug('Filesize in signature: %s' % sigSize)

    decompressSize = len(decompressData) +8
    debug('Filesize decompressed: %s' % decompressSize)

    check((sigSize == decompressSize), 'Length not correct, decompression failed')
    header = list(struct.unpack("<8B", inData[0:8]))
    header[0] = ord('F')

    debug('Generating uncompressed data')
    return struct.pack("<8B", *header) + decompressData

def zip(inData, compression):
    if(compression == 'lzma'):
        check((inData[0] != 'Z'), "already LZMA compressed")

        rawSwf = unzip(inData);

        debug('Compressing with lzma')
        compressData = pylzma.compress(rawSwf[8:], eos=1)
        # 5 accounts for lzma props

        compressSize = len(compressData) - 5

        header = list(struct.unpack("<12B", inData[0:12]))
        header[0]  = ord('Z')
        header[3]  = header[3]>=13 and header[3] or 13
        header[8]  = (compressSize)       & 0xFF
        header[9]  = (compressSize >> 8)  & 0xFF
        header[10] = (compressSize >> 16) & 0xFF
        header[11] = (compressSize >> 24) & 0xFF

        debug('Packing lzma header')
        headerBytes = struct.pack("<12B", *header);
    else:
        check((inData[0] != 'C'), "already zlib compressed")

        rawSwf = unzip(inData);

        debug('Compressing with zlib')
        compressData = zlib.compress(rawSwf[8:])

        compressSize = len(compressData)

        header = list(struct.unpack("<8B", inData[0:8]))
        header[0] = ord('C')
        header[3]  = header[3]>=6 and header[3] or 6

        debug('Packing zlib header')
        headerBytes = struct.pack("<8B", *header)

    debug('Generating compressed data')
    return headerBytes+compressData

def process(infile, outfile, operation='unzip', compression='zlib'):
    fi = open(infile, "rb")
    infileSize = os.path.getsize(infile)
    inData = fi.read()
    fi.close()
    
    debug('Reading ' + os.path.basename(infile) + ' ver ' + inData[0:3])

    #check((inData[1] == 'W') and (inData[2] == 'S'), "not a SWF file")
    if not ((inData[1] == 'W') and (inData[2] == 'S')):
        return

    if(operation=='unzip'):
        outData = unzip(inData)
        
        if len(outData) == 0:
            return
        
        increment = round(100.0 * len(outData) / infileSize) - 100
        print 'File decompressed, size increased: %d%%' % increment
    else:
        compression = compression == 'lzma' and 'lzma' or 'zlib'
        outData = zip(inData, compression)
        decrement = increment = 100 - round(100.0 * len(outData) / infileSize)
        print 'File compressed with %s, size decreased: %d%% %s' % (compression, decrement,
            decrement<0 and '\n\nNotice: Recompressing may cause filesize increased' or'')

    fo = open(outfile, 'wb')
    fo.write(outData)
    fo.close()

if __name__ == "__main__":
    currentDir = os.getcwd()
    if len(sys.argv) > 1:
        currentDir = sys.argv[1]

    files = []
    if os.path.isdir(currentDir):
        files = os.listdir(currentDir)
    else:
        # Arg is file path?
        files = [ currentDir ]
        currentDir = os.path.dirname(os.path.abspath(currentDir))

    outputDir = os.path.join(currentDir, "unzip")
    if not os.path.isdir(outputDir):
        os.mkdir(outputDir)

    scriptFile = os.path.basename(sys.argv[0])

    for inputFile in files:
        if os.path.isdir(inputFile):
            continue

        [name, ext] = os.path.splitext(os.path.basename(inputFile))
        outputFile = os.path.join(outputDir, name + "_unzip" + ext)
        inputFile = os.path.join(currentDir, os.path.basename(inputFile))
        process(inputFile, outputFile)

    sys.exit(0)

2015-02-14

CFA, SEM từ từ rồi cũng ngấm ...

Ngày gần Tết, rảnh rỗi note lại cho nhớ...

Mình làm luận văn cơ sở lý thuyết này nọ từ cách đây 2 năm. Xong rồi lấy data, rồi tập tành phân tích với AMOS. Thiệt ra thì đến giờ vẫn dậm chân tại đó, mình không muốn đổi sang 1 cái khác vì cảm thấy có cái gì đó ko trọn vẹn. Cái bằng thì ko có ảnh hưởng gì quan trọng với công việc của mình, cũng ko có gì quá đặc biệt. nhưng có nhiều ý nghĩa khác, cảm giác "đầu hàng" ko dễ chịu lắm. Nói chung mình cũng rút ra nhiều điều. Lúc đầu cũng coi tá lả mọi thứ nhưng hình như ko thể lĩnh hội nổi vì nó quá lung tung mà ko có hệ thống gì cả. Sách download về thì 1 đống nhưng đọc 1 đoạn là thấy ko ăn nhập gì (tâm lý muốn đọc liền xài liền). Sau đó thì bận quá nên mình cũng cứ để vậy, lâu lâu buồn thì lại search và đọc tiếp cuốn của Kline (thiệt là khó nhai). Thế rồi phải coi lại hết 1 loạt các thứ, từ thống kê tới những thứ đã từng học từ lâu lắc mà mình đã từng nghĩ cũng ko cần hiểu nhiều về mặt toán học của nó như PCA, PAF, EFA... Thế mới nói đời rất "ngu", lúc đi học thì không học cho đàng hoàng, lúc cần thì mới lôi ra. 

Mà nhiều cái gọi là tutorial trên Internet cũng rất là "tào ...". Mình lấy ví dụ 1 cái cơ bản như CFA vs SEM là gì chẳng hạn thì trong những cái mình download lúc đầu cũng đã sai tè le, nói chung là cứ blah blah mà sai be bét ra, cơ bản là những người viết ra cũng ko hiểu (nguy hiểm thật ... làm mình cũng hoảng). Viết thì viết là phân tích CFA với AMOS mà lại chưng cái model của SEM, rồi cũng phân tích đánh giá tá lả (may sao 2 cái nó cùng một cách phân tích)? Mà ngay trong những luận văn mình có được cũng ghi quy trình nghiên cứu chung chung dạng tránh né và cũng chạy SEM xong thôi.

Nếu mà để ý kỹ thì trên wiki có 1 đoạn sẽ dễ hiểu 
CFA is also frequently used as a first step to assess the proposed measurement model in a structural equation model. Many of the rules of interpretation regarding assessment of model fit and model modification in structural equation modeling apply equally to CFA. CFA is distinguished from structural equation modeling by the fact that in CFA, there are no directed arrows between latent factors. In other words, while in CFA factors are not presumed to directly cause one another, SEM often does specify particular factors and variables to be causal in nature. In the context of SEM, the CFA is often called 'the measurement model', while the relations between the latent variables (with directed arrows) are called 'the structural model'.

Tức là không có có direct arrow giữ các latent factor. Mà latent factor hay latent variable thì không được đo trực tiếp, ký hiệu bằng cái hình ellipse.

Học hành mà có người chỉ dẫn thì rất là nhanh, còn mò thì rất là lâu nhưng từ từ thì sẽ ngấm :D

2014-09-15

Error when installing windows SDK 7.1

Thực hiện install các bước như sau:

Download Microsoft Windows SDK for Windows 7 and .NET Framework 4 (ISO)
http://www.microsoft.com/en-us/download/details.aspx?id=8442
  • GRMSDK_EN_DVD.iso is a version for x86 environment. 
  • GRMSDKX_EN_DVD.iso is a version for x64 environment. 
  • GRMSDKIAI_EN_DVD.iso is a version for Itanium environment.
> download GRMSDKX_EN_DVD.iso cho x64

Một số lỗi có thể tham khảo tại đây:
http://blogs.msdn.com/b/windowssdk/archive/2009/09/16/windows-7-sdk-setup-common-installation-issues-and-fixes.aspx

Một số lỗi khác:
  • Có installed Microsoft Visual Studio C++ 2010 SP1 (Visual Studio 2010 SP1).
  • Có .NET Framework 4.5/4.6 installed (Visual Studio 2012/2013)
Thực hiện:
  • Uninstall Visual Studio C++ 2010 Redist packages
  • Uninstall .NET Framework 4.5/4.6.
  • Install SDK 7.1
  • Reinstall Visual Studio C++ 2010 Redist packages
  • Reinstall .NET Framework 4.5/4.6.
Microsoft Visual Studio C++ 2010 SP1 already installed (both SDK 7.1 and VC++ 2010 SP1 installed)
> Apply the SDK 7.1 patch
Download Microsoft Visual C++ 2010 Service Pack 1 Compiler Update for the Windows SDK 7.1

SDK 7.1 was installed (without Microsoft Visual C++ 2010 SP1)
> Upgrade Microsoft Visual Studio 2010 to SP1

Microsoft Visual Studio 2010 Service Pack 1 (Installer)
Xem Additional Information for ISO format

Microsoft Visual C++ 2010 SP1 Redistributable Package (x64)

2014-02-04

Create a .deb Debian package (tạo một package.deb)

Để tạo một .deb package có thể tham khảo các tài liệu

How to create Debian packages

Mình chỉ tóm tắt thôi, nó gồm các bước như sau:

  1. Tạo thư mục dạng ${PACKAGE_NAME}_${VERSION}_${ARCHITECTURE}, ví dụ your-app_0.4.5-r5_i386.

    Nếu build .deb cho Ubuntu có thể chỉ định thêm Ubuntu version ví dụ your-app_0.4.5-r5ubuntu1_i386 có nghĩa là version 1 dành cho Ubuntu build từ version 0.4.5-r5 dành cho Debian.

  2. Tạo các subdirectories cho các file sẽ install, ví dụ:
    /usr/bin ‣ your-app
    /usr/lib/nautilus/extensions-03 ‣ chứa extension cho Nautilus như libnautilus-your-app.so
    /usr/share/doc, /usr/share/man ‣ chứa file help, manual
    /usr/share/locale ‣ file ngôn ngữ, /usr/share/menu.
    /opt/your-app/logo_32.xpm

  3. Tạo thư mục DEBIAN trong package directory. Trong thư mục DEBIAN chứa các file như control, conffile, md5sums, postinst, postrm, preinst, prerm. Có thể tham khảo từ các .deb package khác bằng cách extract nội dung các .deb có sẵn. Thông thường các .deb được cache trong /var/cache/apt/archives. Để xem .deb có nội dung gì có thể dùng ar –t ví dụ

    ar -t /var/cache/apt/archives/firefox_15.0.1+build1-0ubuntu0.11.10.1_i386.deb.
    

    Để extract dùng ar –x sau đó dùng tar để xem nội dung các file nén.
    Có thể dùng tool dpkg-deb để extract nội dung file .deb, eg.

    dpkg-deb -x .../app.deb ~/workspace/app
    dpkg-deb -e .../app.deb ~/workspace/app/DEBIAN
    

  4. Nội dung file DEBIAN/control có thể giống file control của các app khác, chỉ cần chỉnh sửa 1 số field.
  5. File DEBIAN/postinst là một script sẽ run bởi dpkg –i sau khi các file trong package được extract. Post-install bắt đầu bằng
    #! /bin/sh Để bảo đảm nếu có error phát sinh, script nên return non-zero exit code bằng set –e để shell exit ngay command đầu tiên không thành công.

  6. File DEBIAN/preinst pre-install
  7. File DEBIAN/prerm pre-remove
  8. File DEBIAN/postrm post-remove
  9. Xóa tất cả các file backup *~, nhất là các file trong DEBIAN/*~

    rm -rf `find package-dir -name '*~'`
    

  10. Tạo file md5sums chứa checksum MD5 cho tất cả các file trong package bằng command

    md5sum `find . -type f | grep -v '^[.]/DEBIAN/'` > DEBIAN/md5sums
    

    Chạy command trong thư mục chứa DEBIAN.

  11. Giá trị của field Installed-Size: là số cuối cùng trong output của command du chạy trong package directory (lưu ý remove backup file). Có thể chỉ summarize kết quả với command như sau:

    du -sx --exclude DEBIAN package-dirname
    -s, --summarize   ‣display only a total for each argument
    -x, --one-file-system ‣skip directories on different file systems
    

  12. Build .deb package bằng

    fakeroot dpkg-deb –b|--build package-dir
    

  13. Kiểm tra bằng

    lintian package-name.deb
    

  14. Để install .deb package chỉ cần double click, dùng command như sau

    sudo dpkg -i package-file.deb
    

    Để uninstall dùng command

    sudo dpkg -r package-name
    


2013-11-14

Download an Google Chrome Extension file (.crx file)

Download file Google Chrome Extension

Đôi khi cần lưu file .crx version cũ khi không muốn cài lại máy và chỉ dùng version mới nhất thì nên download file .crx. Tuy nhiên nếu mở bằng Google Chrome thì cũng khó download được. Cách tốt nhất là dùng 1 chương trình khác download, dùng browser khác hoặc IDM.

Đầu tiên là vào Chrome Extension tìm ID của extension cần lưu.
Sau đó điền vào đường dẫn 

https://clients2.google.com/service/update2/crx?response=redirect&x=id%3Dxxxxxx%26uc

Phần màu xanh là phần sẽ điền ID vào. Ví dụ ID của Adblock Plus là cfhdojbkjhnklbpkdaibdccddilifddb

Vậy URL để download là 
https://clients2.google.com/service/update2/crx?response=redirect&x=id%3Dcfhdojbkjhnklbpkdaibdccddilifddb%26uc

2013-11-09

Unlock and jailbreak iPhone

Cóp nhặt 1 số thứ liên quan khi dev team nhận được 1 cái iPhone cần phải xử

Unlock là gì, jailbreak là gì?

Là 2 quá trình khác nhau. Tuy nhiên unlock thì cần jailbreak.
Jailbreak là quá trình can thiệp để có thể toàn quyền điều khiển iPhone (lấy quyền root).
Unlock là gì? Can thiệp vào baseband để sử dụng SIM của bất kỳ nhà mạng nào à xem baseband ở phần sau à nếu không unlock thì ko call được. Unlock yêu cầu phải jailbreak trước, sau khi jailbreak xong iPhone sẽ có thể cài appà cài unlock tools như ultrasn0w để unlock. Tất nhiên quá trình unlock còn phụ thuộc nhiều yếu tố trong đó chủ yếu là version của baseband.

Baseband là gì?

Firmware là gì à1 dạng giữa phần mềm và phần cứng.
Baseband thực hiện điều khiển các loại sóng bao gồm sóng điện thoại. Nên để call được với iPhone locked phải can thiệp BB. Khi nâng cấp FW thông thường nâng cấp cả BB. Có thể hạ FW nhưng khi hạ FW thì không hạ được BB. Tại sao phải giữ BB à để thực hiện unlock vì tool unlock chỉ support 1 số BB. Ví dụ: ultrasn0w chỉ support unlock 3GS với các BB sau: 0.6.15, 04.26.08, 05.11.07, 05.13.01, 05.12.01.

Kiểm tra BB của iDevice Settings à General à About à Modem Firmware
Nếu máy chưa activate (dính ở Emergency Call) thì dùng f0recast
Các tools cần thiết có thể download tại đây http://ih8sn0w.com/

Boot loader là gì?

Là đoạn code thực hiện quá trình kiểm tra và nạp firmware theo cách Apple mong muốn. Khi iBoot (boot loader của iPhone) được kích hoạt thì không thể downgrade hay restore custom FW.

Recovery mode là gì?

Là quá trình restore hoặc upgrade firmware có nạp iBoot. Để thực hiện cần phải đưa về recovery mode. Ở chế độ này trên màn hình sẽ hiện cọng cáp kết nối logo iTunes.
Cách đưa về recovery mode :
1. Tắt nguồn, tháo cáp
2. Giữ phím Home
3. Trong khi giữ phím Home thì cắm cáp vào
4. Tiếp tục giữ đến khi hiện hình cái cáp và mũi tên hướng lên logo Itunes là máy đã đuợc đưa về Recovery mode.
Cách thoát khỏi Recovery mode:
Giữ cùng lúc phím Home + Power trong 10s đến khi Iphone tắt.

DFU mode là gì?

Là Device Firmware Upgrade, như đã nói đây là 1 chế độ đặc biệt cần khi downgrade firmware. Tại mode này iBoot và OS sẽ bị bỏ qua, iTunes vẫn nhận iPhone nhưng mà hình iPhone đen thui.
Để enter mode này có thể dùng các tool hỗ trợ để việc thực hiện dễ dàng hơn.

Thực hiện manual như sau:
1. Chạy iTunes
2. Cắm phone vào PC
3. Chờ iTunes nhận (detected) được iphone
4. Bấm và giữ nút Power (ở trên) khoảng 3s . Sau đó bấm tiếp nút Home (nút tròn) và giữ (trong khi vẫn giữ nút Power) khoảng 10s.
5. Trong khoảng 3s thì iPhone sẽ tắt và khởi động lại. Màn hình sẽ tối đen. Lúc này đếm nhẩm trong đầu từ 1 -10, khi đếm tới 10 thì buông nút Power ra nhưng vẫn bấm và giữ nút Home. Nên để ý là khi buông nút Power ra thì màn hình phải vẫn còn tối đen. Nếu lúc buông Power mà quả táo đã hiện lên là đã chậm tay và phải làm lại từ đầu. Cái mẹo ở lúc này là phải buông Power trước khi quả táo xuất hiện!
6. Lúc này tay vẫn còn giữ nút Home, chờ thêm vài giây nữa thì iTunes sẽ báo là "detect phone in DFU mode". Lúc này có thể buông nút Home.
Cách thoát khỏi DFU mode (chỉ hữu dụng khi mắc kẹt và áp dụng luôn):
Giữ Home và Power trong khoảng 30s cho đến khi nào iTunes báo đã ngắt kết nối với iPhone thì thôi.

Activation là gì?

Kích hoạt iPhone qua screen Emergency Call và vào được màn hình chính là springboard.
Nếu là bản quốc tế thì chỉ cần cắm vào iTunes. 1 dạng khác là cần cắm SIM (SIM lock) của nhà mạng để unlock à gọi là activate không cần jailbreak
Nếu iPhone lock à cần jailbreak hay gọi là hacktivate (hacktivation).

SHSH là gì, ECID là gì?

ECID được viết tắc từ chữ Exclusive Chip ID là mã số của 1 con chip nhỏ mà Apple đã gắn vào Iphone 3GS và Ipod Touch 3G. Apple có thể chứng thực được iPhone nào khi kết nối với Server của Apple. ECID không thể thay đổi được bằng software, chỉ có thể thay đổi bằng cách thay chip khác.
SHSH như là một tờ chứng nhận cho mã số đó dạng file có ext là shsh. SHSH được lưu trữ trên Server của Apple, khi restore iPhone của mình, bước thứ 2 là gian đoạn "Verifying with Apple Server". Đó chính là lúc Itunes đã kết nối với server và đang kiểm chứng xem ECID của mình có hợp lệ hay không thông qua file .shsh đã lưu tại đó. Cydia có hỗ trợ backup SHSH.
Tại sao phải backup SHSH tại Cydia. Apple không cho restore về phiên bản thấp hơn trừ phiên bản gốc. Tức Apple không cung cấp chứng thực cho việc hạ hay restore xuống FW thấp hơn FW hiện tại khi không có SHSH. Thông thường sau 1 thời gian ra FW mới Apple sẽ closed luôn FW cũ tức chỉ có thể nâng cấp lên FW mới nhất.
Khi restore về phiên bản cũ hơn thì trong giai đoạn verifying với server phiên bản đó phải được server hỗ trợ. Có 2 cách giả server Apple iTunes: server nào online đã có sao lưu SHSH (hiện tại có Cydia của Saurik) hoặc tạo local server dùng file đã lưu có tại local. Phải chỉnh file hosts để chuyển server của iTunes là gs.apple.com thành server mong muốn. Khi restore về FW thấp hơn FW hiện hành mà không được Apple hỗ trợ thì phải có bản sao lưu SHSH để tạo custom firmware.

Backup và thao tác với SHSH

Hai tools dùng backup SHSH là iFaith và TinyUmbrella (yêu cầu phải cài JRE)
Có thể dùng iFaith kiểm tra SHSH đã lưu của iPhone, fetch SHSH về từ server nếu có, backup SHSH lên Cydia
Dùng sn0wbreeze để tạo custom FW à dung restore FW mà iPhone ko bị nâng baseband.

Untethered jailbreak và tethered jailbreak

Untethered jailbreak còn gọi là jailbreak “không dính cáp” JBU khác với  tethered jailbreak: nếu chỉ tethered jailbreak thì trong trường hợp máy hết pin hay tắt nguồn nói chung là khi muốn chạy một app JB nào thì phải thực hiện 1 vài thao tác (cắm cable à dùng redsn0w à chạy Just Boot).

BootROM cũ và BootROM mới

Thời điểm Apple phát hành FW iOS 4.0, Dev-Team chỉ tìm được kẽ hở của FW có thể jailbreak cho 3GS Old-BootRom trong khi đó không thể tìm cách jailbreak New-BootRom. Do thấy Old-BootRom bị "hở sườn" nên Apple thay đổi loại iBoot mới cho 3GS là New-BootRom (iBoot-359.3.2).

Ngoài ra, sau khi sản xuất iPhone 4, Apple vẫn tiếp tục sản xuất The New 3GS 8GB với chip Toshiba, mục đich ngăn chận máy Lock nâng baseband của iPad (0.6.15) để unlocked (ultrasn0w hỗ trợ unlock BB 0.6.15). Đó là các The New 3GS 8GB sản xuất từ tuần 33 năm 2011 trở về sau. Serial Number: xx133xxxxxx, firmware 4.3.5, BB 5.14 (một số thông tin khác là từ tuần 27 năm 2011 trở về sau).

Các The New 3GS 8GB này khi jailbreak bằng cách dùng baseband của iPad 0.6.15 sẽ bị lỗi "NO ALL", mất WiFi, Bluetooth, ECID, IMEI. Đồng thời iTunes báo lỗi (-1), và máy bị treo hình cáp dĩa. Giang hồ đồn đây là loại baseband "Emergency Boot Loader" (EBL). Các máy The New 3GS 8GB bị "NO ALL" iTunes Error (-1) không thể restore và chỉ có thê gửi trả bào hành nếu còn thời hạn.

Ví dụ, số serial của iPhone 4 thường có cấu trúc AABCCDDDEEF, trong đó:
AA = Nhà máy sản xuất và ID của máy móc
B: Năm sản xuất (là chữ số đứng cuối mỗi năm, ) 9=2009, 0=2010, 1=2011, 2=2012)
CC: tuần sản xuất
DDD: Unique identifier (tuy nhiên không liên quan tới UDID của sản phẩm)
EE: Màu sản phẩm
F: Kích cỡ bộ nhớ, trong đó S là 16GB và T là 32GB

Với các version cũ hơn thì quy tắc khác một chút. OSX Daily còn cung cấp một bảng hướng dẫn dễ đọc hơn với 3 ký tự cuối cùng của số serial:
VR0 (iPhone 2G 4GB màu bạc)
WH8 (iPhone 2G 8GB màu bạc)
0KH (iPhone 2G 16GB màu bạc)
Y7H (iPhone 3G 8GB màu đen)
Y7K (iPhone 3G 16GB màu đen)
3NP (iPhone 3GS 16GB màu đen)
3NR (iPhone 3GS 32GB màu đen)
3NQ (iPhone 3Gs 16GB màu trắng)
3NS (iPhone 3Gs 32GB màu trắng)
A4S (iPhone 4 16GB màu đen)
A4T (iPhone 4 32GB màu đen)

Do đó với mỗi loại BootROM thì việc jailbreak sẽ thực hiện khác nhau à nếu dung OLD BootROM thì có nhiều lợi thế hơn khi jailbreak.

BootROM cũ có lỗi vì thế có thể thực hiện untethered jailbreak (không dính cáp) và đồng thời cho phép "bypass" signature check (SHSH) khi restore custom FW à lợi hại nếu có OLD BootROM.

Đưa iPhone về DFU mode bằng iReb à có số giây để biết cách thực hiện à cắm iPhone vào để iTunes nhận, iPhone đang bật à thực hiện theo iReb.
Nếu bị dính recovery mode không thoát được theo cách thông thường à dùng TinyUmbrella để thoát recovery mode

Kiểm tra BootROM là OLD hay NEW bằng cách dung iDetector (iPhone phải đưa về DFU mode trước)

Thực hiện

Apple hiện tại đang để 2 FW active cho 3GS là FW 4.1 và FW 6.1.3.
Kiểm tra baseband à nếu là BB 6.15 thì dùng Redsn0w để downgrade BB 05.13.04 à nếu là BB 5.14 , 5.15 , 5.16 (những thằng không được hỗ trợ) thì nâng lên BB 6.15 rồi làm 1 lần nữa để hạ xuống BB 5.13, ngay cả khi device chưa bao giờ có BB 05.13.04 (đừng hỏi vì sao làm được).  
Tại sao hạ xuống BB 05.13 là theo thông tin thì BB này ít tốn pin hơn BB 6.15 và quan trọng iPhone sẽ bị mất chức năng như định vị GPS bởi vì BB 06.15.00 của iPad không chứa bộ nhớ bản đồ và các lệnh giao tiếp Read/Write với chip GPS.
Nếu máy từ tuần 34 của 2011 trở về sau thì theo cảnh báo của redsn0w không nên up lên BB 6.15 à có thể bị dính NO ALL à QUÁ ĐEN à chỉ có nước chờ tool unlock fix thôi.
Kiểm tra nếu OLD BootROM thì OK rồi, nếu NEW BootROW thì phải có SHSH à xem lại backup SHSH à dùng sn0wbreeze để tạo custom FW à restore lại FW 5.1.1 nếu có SHSH của FW 5.1.1. Nếu không có thì bó tay à chỉ có thể dùng active FW là FW 4.1 hoặc FW 6.1.3 và các FW có backup SHSH.

Tóm lại thực hiện như sau:
Dùng redsn0w JB và nâng BB 6.15 à JB và hạ BB xuống 5.13
Nếu chưa lên FW 6.1.3, tạo custom FW 6.1.3 bằng sn0wbreeze  à restore không nâng BB

Download 6.1.3 nếu cần sn0wbreeze  iPhone2,1_6.1.3_10B329_Restore.ipsw

Đảm bảo redsn0w chạy quyền admin, mode compatibility với Windows XP SP2/SP3
Chọn Extract à Select IPSW à chọn FW 6.0 (lưu ý là 6.0 chứ không phải 6.1.3) à Back chọn JB à chỉ check Install baseband Ipad
Làm thêm 1 lần nữa để hạ BB, đồng thời check install Cydia luôn.
Sau bước này thì vẫn chưa có Cydia để install ultrasn0w à chạy Just Boot (Extract à Select IPSW cũng chọn FW 6.0 à đưa máy về DFU chọn Extras à Just Boot) à iPhone hiện hình quả dứa.
Như vậy là Jailbreak Tethered xong à search & install ultrasn0w trong Cydia à unlock.


2013-04-05

Bypass exception for developing purpose "Trust anchor for certification path not found"

Original: http://stackoverflow.com/questions/6825226/trust-anchor-not-found-for-android-ssl-connection

Dùng bypass exception verify SSL (develop only) trong trường hợp gặp lỗi do cert ko match. Gọi trước khi execute HTTP request


/**
 * Trust every server - dont check for any certificate
 */
private static void trustAllHosts() {
       // Create a trust manager that does not validate certificate chains
       TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
              public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                     return new java.security.cert.X509Certificate[] {};
              }

              public void checkClientTrusted(X509Certificate[] chain,
                           String authType) throws CertificateException {
              }

              public void checkServerTrusted(X509Certificate[] chain,
                           String authType) throws CertificateException {
              }
       } };

       // Install the all-trusting trust manager
       try {
              SSLContext sc = SSLContext.getInstance("TLS");
              sc.init(null, trustAllCerts, new java.security.SecureRandom());
              HttpsURLConnection
                           .setDefaultSSLSocketFactory(sc.getSocketFactory());

              HttpsURLConnection
                           .setDefaultHostnameVerifier(new HostnameVerifier() {
                                  @Override
                                  public boolean verify(String hostname,
                                                SSLSession session) {
                                         return true;
                                  }
                           });
       } catch (Exception e) {
              e.printStackTrace();
       }
}