BLOG main image
분류 전체보기 (224)
Reversing (13)
Pwnable (4)
Linux Kernel (3)
Crypto (2)
Wargames (68)
Programming (18)
Write Up (32)
Project (22)
Web (2)
My Life (52)
Memo (3)
etc (2)
발표자료 (1)
40,198 Visitors up to today!
Today 2 hit, Yesterday 21 hit
daisy rss
tistory 티스토리 가입하기!
2017.08.29 14:16


두 값을 더하는 add연산을 하는 함수를 만들어야 한다는 상황을 가정해보자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
 
/*
int add(int a, int b) {
    return a + b;
}
double add(double a, double b) {
    return a + b;
}
std::string add(std::string a, std::string b) {
    return a + b;
}
*/
 
template <typename T>
T add(T a, T b) {
    return a + b;
}
 
// 특수화 (Specialization)
template <typename T>
int add(int* a, int* b) {
    return *+ *b;
}
 
int main(void) {
    int a = 10, b = 20;
    double c = 10.4, d = 20.4;
    std::string s = "Hello", t = "World";
    int* pA = &a;
    int* pB = &b;
 
    int sum = add(a, b);
    double sum2 = add(c, d);
    std::string sum3 = add(s, t);
    int pSum = add<int*>(pA, pB);    // using specialization template
 
    std::cout << pSum << std::endl;
}
cs

템플릿이 없었다면 주석처럼 각 타입마다 모두 add함수를 만들어서 사용해야 할 것이다.
그런데 템플릿을 사용하면 이렇게 타입에 대해서 T로 표시하고 어찌어찌 해서 들어오는 타입대로 더할 수 있게 된다.
특정 자료형만 따로 정의할 일이 있으면 위에처럼 특수화를 해서 정의하면 된다.

그럼 int와 double은 어떻게 더해야 하는가? 
int + double은 double이지만 어떤 값이 double인지 알아내기는 쉽지 않다.
여러가지 대처 방법이 있을 수 있는데 가장 무난하고 권장되는 방법은

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
 
template <typename T1, typename T2>
auto add(T1 a, T2 b) -> decltype(a + b) {
    return a + b;
}
 
int main(void) {
    auto e = 10.4f;
    decltype(e) f = 24.5f;    // e의 타입으로 정의
 
    int a = 10;
    double b = 20.4;
 
    std::cout << add(a, b) << std::endl;
    std::cout << add(b, a) << std::endl;
}
cs

이렇게 auto로 반환하되 auto의 타입을 decltype을 이용해서 a + b의 타입으로 맞춰주면 된다.

다음은 가변인자에 대한 가변 템플릿이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
 
/*
int sum(int a, int b) {
    return a + b;
}
int sum(int a, int b, int c) {
    return a + b + c;
}
int sum(int a, int b, int c, int d) {
    return a + b + c + d;
}
int sum(int a, int b, int c, int d, int e) {
    return a + b + c + d + e;
}
// ...
*/
 
// C++11 : Variadic Template (가변 템플릿)
template <typename T, typename... Args>
T sum(T a, Args... args) {
    return a + sum(args...);
}
 
template <typename T>
T sum(T a) {
    return a;
}
 
int main(void) {
    int a = 1, b = 2, c = 3;
 
    std::cout << sum(a, b) << std::endl;
    std::cout << sum(a, b, c) << std::endl;
}
cs

가변 템플릿이 없었다면 주석에 있는 것처럼 모든 인자의 개수에 맞춰서 다 정의를 미리 해주어야한다.
그런데 가변 템플릿을 사용하면 그럴 필요가 없다.

가변 템플릿은 재귀적인 형태로 이루어지며 가변 인수를 받는 템플릿 함수와 재귀적으로 돌다가 인자가 하나만 남았을 때 처리하는 함수 총 두개가 필요하다.

가변 템플릿은 위에 처럼 쓰면 댄다.
그리고 저 가변 템플릿은 코드상에서는 재귀지만 컴파일 타임때 재귀는 모두 풀리고 그냥 함수로 풀려서 실제 컴파일 하면 재귀로 실행되지 않는다.
그래서 재귀함수의 오버헤드가 발생하지 않는다.

그럼 가변 템플릿과 이것 저것을 응용해서 

1
2
3
4
5
6
#include <iostream>
 
int main(void) {
    std::cout << 'a' << 3 << "String" << 3.14 << std::endl;
    PrintList('a'3"String"3.14);
}
cs

4번 라인과 5번 라인이 똑같이 나오도록 PrintList함수를 만들어보자.

물론 인자 개수와 타입은 각각 바뀔 수 있다.

알아서 만들자

'Programming > C++' 카테고리의 다른 글

C++에서 문자열 EOF까지 입력받고 출력하기  (0) 2018.04.24
c++ 템플릿 공부  (0) 2017.08.29
Lvalue와 Rvalue  (0) 2017.05.20
Name
Password
Homepage
Secret
2017.08.13 00:43


따로 ida에서 제공하는 dbgsrv에서 쓸만한게 없다면 gdbserver를 올려서 디버깅 해야한다.
서버에 gdbserver를 static으로 서버 환경에 맞게 컴파일하거나 이미 컴파일 된 파일을 다운 받아서 올리고 

"sudo ./gdbserver 127.0.0.1:port ./binary" 이렇게 실행하면 된다. port부분에 1337, 7777처럼 포트 번호를 넣으면 된다. (해당 포트포워딩은 외부로 해 둬야 한다.)

가끔씩 sudo를 안해서 ida에서 오류가 날 때가 있으니 해주는게 좋다.

그리고 ida로 debugger를 Remote GDB debbuger로 설정하고 Debugger - Process Options에서 Application, Input file을 서버에서의 파일 위치로 잡고, Parameters는 인자, Hostname에 서버 주소를, Port에 아까 열은 포트를 입력하면 된다.

그러면 디버깅을 할 수 있다.

그런데 가끔씩

이런 에러가 날 때가 있다. ("Single-stepping a thread failed; possibly stub does not support single-stepping Try disabling the single-step functionality in debugger-specific options.")

이 때는 Debugger - Debugger Options - Set specific options - Use stepping support 옵션에 체크를 해제해주면 정상적으로 디버깅 할 수 있다.

'Reversing > Debugging Tech' 카테고리의 다른 글

gdbserver 디버깅  (0) 2017.08.13
OS 동적 디버깅(vmware)  (1) 2016.06.22
16bit DOS Debugging  (0) 2016.02.03
IDA Linux Remote Debugging  (0) 2015.09.19
Name
Password
Homepage
Secret
2017.08.11 08:32


이번엔 뮤쀼로 참가했다.

Web - 50, 100, 150, 200
Forensic - 50, 100
Reversing - 50, 100, 150, 200
Pwnable - 50, 100, 150, 200
Misc - 50, 100, 150, 200

제 15회 YISF 문제풀이 보고서 이태양(뮤쀼).pdf

리버싱 300 바이너리랑 풀이 코드
https://github.com/5unKn0wn/ctfs/tree/master/yisf2017/reversing300

리버싱 300 가상화 문제라서 오래걸릴 줄 알고 안풀었는데 분석 해보니까 xor만 하는 생각보다 간단한 가상화였다.

'Write Up' 카테고리의 다른 글

YISF 2017 예선 Write-Up  (2) 2017.08.11
ASIS CTF Quals 2017 Reversing Flour  (2) 2017.04.10
YISF 2016 본선 리버싱 문제 풀이  (5) 2016.12.01
2016 Whitehat Contest 예선 Write-Up  (3) 2016.10.13
2016 Layer7 CTF Write-UP  (4) 2016.09.07
YISF 2016 예선 Write-Up  (2) 2016.08.19
| 2018.10.24 18:18 | PERMALINK | EDIT/DEL | REPLY
비밀댓글입니다
5unKn0wn | 2018.11.07 23:40 신고 | PERMALINK | EDIT/DEL
앗 실제로 문제를 풀 때는 웹페이지에서 문제를 풀었습니다.
다만 라이트업을 작성할 때 간결하게 쓰기 위해서 풀이 리퀘스트를 리눅스에서 보내 플래그를 획득한 부분만 캡쳐한 것입니다
Name
Password
Homepage
Secret