Android에서, 안드로이드를 통째로 컴파일 하지 말고, 만약 커널만 수정하고 싶다면?


순정롬을 다운받아서, zImage(kernel)만 바꿔 친 후, 안드로이드에 롬을 올리면 된다.


그 과정을 Ubuntu 12.04 64bit + Nexus 5에서 진행했을때는 아래와 같다.


예를 들어, 안드로이드에 tcp_probe 모듈을 추가하도록 해본다.


1. Kernel build


먼저, 커널을 다운로드 받는다.

git clone https://android.googlesource.com/kernel/msm.git

# cd msm

# git checkout 3.4.0-gadb2201


원하는 부분을 수정한다.

그리고, 컴파일에 필요한 툴을 다운받는다.
# cd ~
# git clone https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6

그리고는, 커널 폴더로 가서, 세팅을 하고,
# export ARCH=arm
# export SUBARCH=arm
# export CROSS_COMPILE=/yourpath/arm-eabi-4.6/bin/arm-eabi-
# make hammerhead_defconfig

TCP_PROBE 사용을 위해서 추가적으로 menuconfig를 열어 필요한 모듈을 체크해야 한다.
# make menuconfig

체크해야 하는 것(순서대로 하지 않으면 옵션이 안보일 수 있음.)
1. [*] Enable loadable module support
2. Enable loadable module support -> [*] Module unloading
3. Enable loadable module support -> [*] Module versioning support
4. Enalbe loadable module support -> [*] Source checksum for all modules
5. General setup -> [*] Kprobes
6. Networking support -> Networking options -> Network testing -> <M> TCP connection probing

위와 같이 체크 후 저장하며 종료


그리고 컴파일

# make -j 4


컴파일이 완료되면, arch/arm/boot/zImage 가 생성된다.

net/ipv4/tcp_probe.ko 도 생성된다.


2. Make a ROM


순정롬을 다운받는다. Nexus 5는 아래의 경로에 있다.

https://developers.google.com/android/nexus/images?hl=ko-KR#hammerheadkot49h


압축을 푼다.

# tar xzvf hammerhead-kot49h-factory-02006b99.tgz


여기서 image-hammerhead-kot49h.zip 의 boot.img를 수정해야 한다.

# mkdir ~/image

# cd ~/image

# cp ~/hammerhead-kot49h/image-hammerhead-kot49h.zip ./

# unzip image-hammerhead-kot49h.zip


boot.img를 언팩하고, zImage를 바꿔 친 후, 리팩해야 하는데 나는 다른사람의 툴을 사용해서 했다.

# cd ~

# wget https://github.com/pbatard/bootimg-tools/archive/master.zip

# unzip master.zip

# cd bootimg-tools-master/

# make

# cd mkbootimg/

# cp mkbootimg /usr/local/bin/

# cp unmkbootimg /usr/local/bin/


이제 바꿔 치기를 한다. (참고로, 보통은 zImage를 사용하지만, 내 경우는 Nexus 5라서, zImage-dtb를 사용하였다.)

# mkdir ~/repack

# cd ~/repack

# cp ~/image/boot.img ./boot.img

# unmkbootimg -i boot.img

# cp ~/msm/arch/arm/boot/zImage-dtb ./zImage

# mkbootimg --base 0 --pagesize 2048 --kernel_offset 0x00008000 --ramdisk_offset 0x02900000 --second_offset 0x00f00000 --tags_offset 0x02700000 --cmdline 'console=ttyHSL0,115200,n8 androidboot.hardware=hammerhead user_debug=31 maxcpus=2 msm_watchdog_v2.enable=1' --kernel zImage --ramdisk ramdisk.cpio.gz -o newboot.img

# cp newboot.img ~/image/boot.img

# cd ~/image

# rm image-hammerhead-kot49h.zip

# zip newimage.zip *

# cp newimage.zip ~/hammerhead-kot49h/image-hammerhead-kot49h.zip


3. Flash


fastboot 모드로, 실행시킨다.

# adb reboot-bootloader

# fastboot oem unlock


그리고, flash를 한다.

# cd ~/hammerhead-kot49h/

# ./flash-all.sh


flash가 끝나고 부팅이 완료되면 기본 설정을 마치고 

바로 ‘개발자 모드 – USB 디버깅’을 체크하고 Nexus Root Toolkit으로 루팅을 시전한다.

루팅이 완료되고 부팅이 되면 바로 BusyBox를 실행하고 SuperSu 루트 권한을 허용하고, 

쓸데없는 메시지 창을 닫고 하단 부 뱅글뱅글 로딩이가 없어지면 또 나오는 메시지 창을 닫고 

왼쪽아래 install 버튼을 누르면 또 창이 뜨는데 거기서 Smart Install을 선택한다.(상단 부 /system/bin 옵션 그대로 둠)

Install이 끝나면 BusyBox 종료


아까 만들어진 tcp_probe.ko 파일을 adb를 사용해 폰에 넣는다.


# adb push ~/msm/net/ipv4/tcp_probe.ko /mnt/sdcard/Download/


이제 adb shell을 열고 관리자 권한을 얻기 위해 su를 입력하고 폰에 뜨는 SuperSU 루트 권한을 허용한다.


# adb shell

$ su


모듈을 저장할 폴더를 만들기 위해 read only인 root를 remount한다.


# mount –o rw,remount /


/lib/modules/ 경로를 생성한다.


# cd /

# mkdir lib

# cd lib

# mkdir modules

# cd modules


이후 경로를 확인하기 위해 modprobe를 입력해본다.


# modprobe

modprobe: can't change directory to '3.4.0-gadb2201-dirty': No such file or directory


에러 메시지를 보고 해당하는 폴더를 만든다


# mkdir 3.4.0-gadb2201-dirty

# cd 3.4.0-gadb2201-dirty


모듈 목록파일 modules.dep을 생성한다.


# vi modules.dep

파일 내용 딱 한줄

kernel/net/ipv4/tcp_probe.ko:


파일을 저장한 후 /lib/modules/3.4.0-gadb2201-dirty/kernel/net/ipv4 끝까지 경로를 생성해준다.


# mkdir kernel

# cd kernel/

# mkdir net

# cd net/

# mkdir ipv4


tcp_probe.ko 파일을 옮겨준다.


# cp /mnt/sdcard/Download/tcp_probe.ko /lib/modules/3.4.0-gadb2201-dirty/kernel/net/ipv4/


tcp_probe를 테스트해본다.


# modprobe tcp_probe full=1

# cat /proc/net/tcpprobe > /mnt/sdcard/Download/tcpprobe.log &


폰에서 인터넷 사용 후 로그를 출력해 보면 정상적으로 작동하는 것을 확인할 수 있다.


# tail /mnt/sdcard/Download/tcpprobe.log


끝.


+ 만약 벽돌이 되었다면.......... (Nexus 5 용)

http://liciousroms.com/nexus5_restore.html


참고

- 안드로이드 순정 롬

https://developers.google.com/android/nexus/images?hl=ko-KR#hammerheadkot49h

- kernel build & boot.img unpack and repack

https://groups.google.com/forum/#!topic/android-kernel/kgxdpN_77x4

- mkbootimg, unmkbootimg

https://github.com/pbatard/bootimg-tools

posted by tunz
  • k1rha 2014.12.02 18:51

    블로깅덕에 엄청 삽질했던 방향이 풀렸네요 ~
    lime.ko 좀 안드로이드에 올릴려고 엄청 삽질했엇는데, BOB나 대전에서 언제 뵈면 밥한끼 사겠습니다 :)

  • md5 2015.04.22 18:04

    안드로이드 리눅스 커널만을 빌드하여 대치 할 경우 커널 버전과 안드로이드 플랫폼이 서로 의존하나요?

    커스터마이징 된 안드로이드마다 커널 바이너리 파일 크기가 많이 다르더라구요.

    커스터마이징 된 안드로이드 A 버전을 사용하고 있는 장치에, 다른 커스터마이징 된 안드로이드 B 버전의 커널 소스를 빌드하여

    서로 다른 곳에서 배포되는 안드로이드 리눅스 커널을 config설정만 장치에 맞게 제대로 되었다면 장치가 동작하는데 전혀 문제가 되지 않는지 궁금합니다.

    • tunz 2015.04.24 16:13 신고

      제가 이쪽 전문은 아니라서 잘은 모르겠는데..
      커널버전업을 하는거라면, 문제가 없을 확률이 클것 같긴 합니다.
      근데 버전업하는 정도가 크면 클수록, 문제가 100% 없을거라고 장담하진 못하겠네요.
      기본적으로는 문제가 없게 만들어야 하는게 맞긴 하지만
      항상 예상하는대로만 되지는 않으니까요
      그냥 해봐야 알것같군요

  • samuro 2016.09.28 15:58

    갤럭시의 경우에 순정롬은 어떻게 구할 수 있나요? 펌웨어와 롬이 다른가요? 원한느 펌웨어는 구했는데 md5파일이라 boot.img를 수정할 수가 없네요

First, it is packed by upx. so just unpack binary.


then, because of undefined instruction(0F 0B), it starts exception handler.

So, strcmp with "oh_nasty_boy!you_hacked_me:(hehe" is just fake.


exception handler is in 0x4010d0.


At 0x4010d0, insert keys and encode input. and finally compare with another real answer 


routine is as follow.


1. exception handler starts

2. insert key to stack

3. xor key with some value in 0x4011C3

4. encode input using key (function 0x401000)

5. compare encoded value to answer


but, I didn't know xor key with what value in third step.

So, it is just brute-force.


script is as follow in python

http://pastebin.com/MnSv30YB


  1. from struct import *
  2. import sys
  3.  
  4. key1 = "86DE9AF8DFF585E9DD85EF".decode('hex')
  5.  
  6. def encode(data,n):
  7.         global key1
  8.         zero_to_100 = []
  9.         i =0
  10.         while i<0x100:
  11.                 zero_to_100.append(i)
  12.                 i+=1
  13.         temp_key1 = list(key1)
  14.         temp_key = [chr(ord(i) ^ n) for i in key1]
  15.         calc_key1 = "".join(temp_key)
  16.  
  17.         i = 0
  18.         v4 = 0
  19.         v8 = 0
  20.         v3 = 0
  21.         while i<0x100:
  22.                 v3 += (zero_to_100[i] + ord(calc_key1[i % 0xB]))
  23.                 v3 = v3 & 0xFF
  24.                 v8 = zero_to_100[i]
  25.                 zero_to_100[i] = zero_to_100[v3]
  26.                 zero_to_100[v3] = v8
  27.                 i+=1
  28.  
  29.         i=0
  30.         v9 = 0
  31.         v10 = 0
  32.         answer = ""
  33.         while i < 0x20:
  34.                 v12 = v10+1
  35.                 v17 = v12
  36.                 v9 += zero_to_100[v12]
  37.                 v9 = v9 & 0xFF
  38.                 v13 = zero_to_100[v12]
  39.                 v15 = zero_to_100[v9]
  40.                 zero_to_100[v12] = v15
  41.                 zero_to_100[v9] = v13
  42.                 k = zero_to_100[(v13 + v15) & 0xFF]
  43.                 answer += chr(ord(data[i]) ^ k)
  44.                 v10 = v17
  45.                 i+=1
  46.  
  47.         return answer
  48.  
  49. def check(data):
  50.         data = list(data)
  51.         for i in data:
  52.                 if ord(i) < 0x20 or ord(i) >= 0x80:
  53.                         return False
  54.  
  55.         return True
  56.  
  57. compare = ""
  58. compare += pack('<L', 0x03C7C8CA)
  59. compare += pack('<L', 0x1F2810FC)
  60. compare += pack('<L', 0x948C7F7A)
  61. compare += pack('<L', 0x2469F92E)
  62. compare += pack('<L', 0xC1277D9F)
  63. compare += pack('<L', 0x7F4509C4)
  64. compare += pack('<L', 0x9745EE75)
  65. compare += pack('<L', 0x1F79AF8D)
  66.  
  67. for n in range(0,0x100):
  68.         xored = encode("1"*32,n)
  69.  
  70.         key = ""
  71.         for i in xored:
  72.                 key += chr(ord(i) ^ ord('1'))
  73.  
  74.         i=0
  75.         answer = ""
  76.         while i< 32:
  77.                 answer += chr(ord(key[i]) ^ ord(compare[i]))
  78.                 i+=1
  79.  
  80.         if check(answer):
  81.                 print answer
  82.                 sys.exit()


'Computer Security > CTF' 카테고리의 다른 글

[Defcon 2014] HJ(2) byhd write up  (0) 2014.05.19
[Defcon 2014] 100 lines exploit  (0) 2014.05.19
[RuCTF 2014 quals] Reversing 500  (0) 2014.03.11
[Codegate 2014 quals] Web 500 write up  (0) 2014.02.24
[secuinside 2013] debugd exploit  (2) 2013.11.28
[Secuinside 2013] angry danbi exploit  (3) 2013.11.27
posted by tunz

linux에서 %gs:0x10 이런식으로 접근할때, gs의 베이스주소를 알아내는법


$ strace -f ./바이너리 2>&1 | grep thread_area


posted by tunz
  • levs 2014.06.25 22:50

    저 명령어의 원리좀 알 수 있을까요?