RE-实验吧/逆向观察&bitwise

本文通过两个实例,介绍了逆向工程的基本思路与技巧。首先,通过分析64位ELF文件,利用IDA逆向了程序的main函数,揭示了正确密码的获取方式。其次,解析了一段Python代码,通过编写解密算法,成功破解了密码验证过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Aliikas-0x05
题目:
实验吧逆向观察
实验吧 bitwise

1.逆向观察

File 一下 64位ELF。

rev50: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.24, BuildID[sha1]=695ac65e2d54e1d05b327b59d37c2d6eb6aba299, not stripped

题目叫逆向观察,那我们就直接IDA看一下,进入mian函数,代码如下:

 if ( argc <= 1 )
  {
    puts("usage ./rev50 password");
  }
  else
  {
    src = 'sedecrem';//8315162673632404845LL,按R字符转换一下
    v6 = 0;
    v7 = 0;
    v8 = 0;
    memcpy(&dest, &src, 9uLL);
    for ( i = 0; i <= 999; ++i )
    {
      if ( !strcmp(argv[1], (&dict)[i]) && !strcmp(&dest, (&dict)[i]) )
      {
        puts("Good password ! ");
        goto LABEL_10;
      }
    }
    puts("Bad ! password");
  }
LABEL_10:
  puts(&byte_40252A);

函数说明:

1.memcpy():C 库函数 void *memcpy(void *str1, const void *str2, size_t n)

从存储区 str2 复制 n 个字符到存储区 str1。

2.int strncmp ( const char * str1, const char * str2, size_t n );

若str1与str2的前n个字符相同,则返回0;若s1大于s2,则返回大于0的值;若s1 小于s2,则返回小于0的值。

那要打印出Good password,那不就应该让!strcmp(argv[1], (&dict)[i]) && !strcmp(&dest, (&dict)[i])都为1嘛,那我们输入的就应该和dest一样…真的有这么简单吗?

./rev50 sedecrem
Bad ! password

emmmmmm这里我就想到了,储存方式的不同(大小端问题),故直接把字符串反转一下:

./rev50 mercedes
Good password !

2.bitwise

题目给出了python代码,如下:

    user_submitted = raw_input("Enter Password: ")
    
    if len(user_submitted) != 10:
      print "Wrong"
      exit()
    
    
    verify_arr = [193, 35, 9, 33, 1, 9, 3, 33, 9, 225]
    user_arr = []
    for char in user_submitted:
      # '<<' is left bit shift
      # '>>' is right bit shift
      # '|' is bit-wise or
      # '^' is bit-wise xor
      # '&' is bit-wise and
      user_arr.append( (((ord(char) << 5) | (ord(char) >> 3)) ^ 111) & 255 )
    
    if (user_arr == verify_arr):
      print "Success"
    else:
      print "Wrong"

那直接写出解密算法即可,这题不是很难0.0

s = [193, 35, 9, 33, 1, 9, 3, 33, 9, 225]
key=[0,0,0,0,0,0,0,0,0,0]
for i in range(10):
    for j in range(128):
        if s[i]==(((j<< 5) | (j >> 3)) ^ 111) & 255 :
            key[i]=chr(j)
        
flag= ''
for i in key:
    flag+=i
print flag

得:ub3rs3cr3t

补充:Big-Endian和Little-Endian的定义如下:

1) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
2) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
举一个例子,比如数字0x12 34 56 78在内存中的表示形式为:
1)大端模式:

低地址高地址
0x120x340x560x78

2)小端模式:

低地址高地址
0x780x560x340x12

可见,大端模式和字符串的存储模式类似。

3)下面是两个具体例子:

16bit宽的数0x1234在Little-endian模式(以及Big-endian模式)CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址小端模式存放内容大端模式存放内容
0x40000x340x12
0x40010x120x34

·32bit宽的数0x12345678在Little-endian模式以及Big-endian模式)CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址小端模式存放内容大端模式存放内容
0x4000x780x12
0x40010x560x34
0x40020x340x56
0x40030x120x78

4)大端小端没有谁优谁劣,各自优势便是对方劣势:

小端模式 :强制转换数据不需要调整字节内容,1、2、4字节的存储方式一样。
大端模式 :符号位的判定固定为第一个字节,容易判断正负。

三、数组在大端小端情况下的存储:
  以unsigned int value = 0x12345678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value:
  Big-Endian: 低地址存放高位,如下:

高地址
buf[3] (0x78)低位
buf[2] (0x56)
buf[1] (0x34)
buf[0] (0x12)高位
低地址

Little-Endian: 低地址存放低位,如下:

高地址
buf[3] (0x12)高位
buf[2] (0x34)
buf[1] (0x56)
buf[0] (0x78)低位
低地址

总结:题略水0.0,但还是锻炼了自己的逆向思维和写脚本的能力
参考资料:https://blog.youkuaiyun.com/ce123_zhouwei/article/details/6971544

//----------------------------------------------------------------------------- // Includes //----------------------------------------------------------------------------- #include <SI_C8051F300_Register_Enums.h> #include <stdio.h> //----------------------------------------------------------------------------- // Global CONSTANTS //----------------------------------------------------------------------------- #define SYSCLK 24500000 // SYSCLK frequency in Hz #define BAUDRATE 115200 // Baud rate of UART in bps SI_SBIT(DE_RE, SFR_P0, 6); //定義P0.6 控制名稱為DE_RE SI_SBIT(LED2, SFR_P0, 1); //定義P0.1 控制名稱為LED2 SI_SBIT(LED1, SFR_P0, 0); //定義P0.0 控制名稱為LED1 SI_SBIT(LED3, SFR_P0, 2); //定義P0.2 控制名稱為LED3 SI_SBIT(LED4, SFR_P0, 3); //定義P0.3 控制名稱為LED4 SI_SBIT(LED5, SFR_P0, 7); //定義P0.7 控制名稱為LED5 //----------------------------------------------------------------------------- // Function PROTOTYPES //----------------------------------------------------------------------------- SI_INTERRUPT_PROTO(UART0_Interrupt, 4); void SYSCLK_Init (void); void UART0_Init (void); void PORT_Init (void); void Timer2_Init (int16_t); void MyDelay (uint16_t Value); #define KEY_DOWN 1 #define KEY_UP 0 #define LED_ON 0 #define LED_OFF 1 //----------------------------------------------------------------------------- // Global Variables //----------------------------------------------------------------------------- #define UART_BUFFERSIZE 6 uint8_t UART_Buffer[UART_BUFFERSIZE]; uint8_t UART_Buffer_Size = 0; uint8_t UART_Input_First = 0; uint8_t UART_Output_First = 0; uint8_t TX_Ready =1; uint8_t RX_Ready =0; static char Byte; uint8_t SnapDown_TimeCnt =0; uint8_t fSnap = 0; uint8_t RecDown_TimeCnt =0; uint8_t fRec = 0; //----------------------------------------------------------------------------- // SiLabs_Startup() Routine // ---------------------------------------------------------------------------- // This function is called immediately after reset, before the initialization // code is run in SILABS_STARTUP.A51 (which runs before main() ). This is a // useful place to disable the watchdog timer, which is enable by default // and may trigger before main() in some instances. //----------------------------------------------------------------------------- void SiLabs_Startup (void) { PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer } //----------------------------------------------------------------------------- // MAIN Routine //----------------------------------------------------------------------------- void main (void) { // enable) PORT_Init(); // Initialize Port I/O SYSCLK_Init (); // Initialize Oscillator UART0_Init(); IE_EA = 1; DE_RE =0; Timer2_Init (SYSCLK / 12 / 1000); // Init Timer2 to generate // 每1ms 計時中斷 while(1) { if(RX_Ready) { RX_Ready = 0; UART_Buffer_Size =0; if(UART_Buffer[3]==0x01)//任一鍵按下 { if(UART_Buffer[4]==0x01)//REC { fRec = KEY_DOWN; RecDown_TimeCnt=0; } else if(UART_Buffer[4]==0x02)//SNAP { fSnap = KEY_DOWN; SnapDown_TimeCnt=0; } else if(UART_Buffer[4]==0x03)//LED UP LED3 = LED_ON; else if(UART_Buffer[4]==0x04)//LED DO LED4 = LED_ON; else if(UART_Buffer[4]==0x05)//Mirror LED5 = LED_ON; } if(UART_Buffer[3]==0x00)//任一鍵放開 { if(UART_Buffer[4]==0x01)//REC { fRec = KEY_UP; } else if(UART_Buffer[4]==0x02)//SNAP { fSnap = KEY_UP; } else if(UART_Buffer[4]==0x03)//LED UP LED3 = LED_OFF; else if(UART_Buffer[4]==0x04)//LED DO LED4 = LED_OFF; else if(UART_Buffer[4]==0x05)//Mirror LED5 = LED_OFF; } IE_ES0 =1; } if(SnapDown_TimeCnt >55 && fSnap == KEY_DOWN) { LED1 = LED_ON; } else if(SnapDown_TimeCnt >55 && fSnap == KEY_UP) { LED1 =LED_OFF; SnapDown_TimeCnt =0; } else if(SnapDown_TimeCnt >45 && SnapDown_TimeCnt <55 && fSnap == KEY_UP) { LED1 = LED_ON; LED2 = LED_ON; MyDelay(1100);//延遲約0.5秒 LED1 = LED_OFF; LED2 = LED_OFF; SnapDown_TimeCnt =0; } if(RecDown_TimeCnt >55 && fRec == KEY_DOWN) { LED2 = LED_ON; } else if(RecDown_TimeCnt >55 && fRec == KEY_UP) { LED2 = LED_OFF; RecDown_TimeCnt =0; } else if(RecDown_TimeCnt >45 && RecDown_TimeCnt <55 && fRec == KEY_UP) { LED4 = LED_ON; LED5 = LED_ON; MyDelay(1100);//延遲約0.5秒 LED4 = LED_OFF; LED5 = LED_OFF; RecDown_TimeCnt =0; } } } //----------------------------------------------------------------------------- // Initialization Subroutines //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // PORT_Init //----------------------------------------------------------------------------- // // Return Value : None // Parameters : None // // Configure the Crossbar and GPIO ports. // // P0.4 digital push-pull UART TX // P0.5 digital open-drain UART RX // //----------------------------------------------------------------------------- void PORT_Init (void) { P0MDOUT |= 0x10; // set UART TX to push-pull output XBR1 = 0x03; // Enable UTX, URX as push-pull output XBR2 = 0x40; // Enable crossbar, weak pull-ups // disabled XBR0 = 0x40; P0MDOUT |= 0x40; } //----------------------------------------------------------------------------- // SYSCLK_Init //----------------------------------------------------------------------------- // // Return Value : None // Parameters : None // // This routine initializes the system clock to use the internal oscillator // at its maximum frequency. // Also enables the Missing Clock Detector. //----------------------------------------------------------------------------- void SYSCLK_Init (void) { OSCICN |= 0x03; // Configure internal oscillator for // its maximum frequency RSTSRC = 0x04; // Enable missing clock detector } //----------------------------------------------------------------------------- // UART0_Init //----------------------------------------------------------------------------- // // Return Value : None // Parameters : None // // Configure the UART0 using Timer1, for <BAUDRATE> and 8-N-1. //----------------------------------------------------------------------------- void UART0_Init (void) { SCON0 = 0x10; // SCON0: 8-bit variable bit rate // level of STOP bit is ignored // RX enabled // ninth bits are zeros // clear SCON0_RI and SCON0_TI bits if (SYSCLK/BAUDRATE/2/256 < 1) { TH1 = -(SYSCLK/BAUDRATE/2); CKCON |= 0x10; // T1M = 1; SCA1:0 = xx } else if (SYSCLK/BAUDRATE/2/256 < 4) { TH1 = -(SYSCLK/BAUDRATE/2/4); CKCON |= 0x01; // T1M = 0; SCA1:0 = 01 CKCON &= ~0x12; } else if (SYSCLK/BAUDRATE/2/256 < 12) { TH1 = -(SYSCLK/BAUDRATE/2/12); CKCON &= ~0x13; // T1M = 0; SCA1:0 = 00 } else { TH1 = -(SYSCLK/BAUDRATE/2/48); CKCON |= 0x02; // T1M = 0; SCA1:0 = 10 CKCON &= ~0x11; } TL1 = 0xff; // set Timer1 to overflow immediately TMOD |= 0x20; // TMOD: timer 1 in 8-bit autoreload TMOD &= ~0xD0; // mode TCON_TR1 = 1; // START Timer1 TX_Ready = 1; // Flag showing that UART can transmit IP |= 0x10; // Make UART high priority IE_ES0 = 1; // Enable UART0 interrupts } //----------------------------------------------------------------------------- // Interrupt Service Routines //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // UART0_Interrupt //----------------------------------------------------------------------------- // // This routine is invoked whenever a character is entered or displayed on the // Hyperterminal. // //----------------------------------------------------------------------------- SI_INTERRUPT(UART0_Interrupt, 4) { if (SCON0_RI == 1) { if( UART_Buffer_Size == 0) { // If new word is entered UART_Input_First = 0; } SCON0_RI = 0; // Clear interrupt flag Byte = SBUF0; // Read a character from UART if (UART_Buffer_Size < UART_BUFFERSIZE) { UART_Buffer[UART_Input_First] = Byte; // Store in array UART_Buffer_Size++; // Update array's size UART_Input_First++; // Update counter } if(UART_Buffer_Size >= UART_BUFFERSIZE) { RX_Ready =1; UART_Buffer_Size =0; IE_ES0 = 0; } } if (SCON0_TI == 1) // Check if transmit flag is set { SCON0_TI = 0; // Clear interrupt flag if (UART_Buffer_Size != 1) // If buffer not empty { // If a new word is being output if ( UART_Buffer_Size == UART_Input_First ) { UART_Output_First = 0; } // Store a character in the variable byte Byte = UART_Buffer[UART_Output_First]; if ((Byte >= 0x61) && (Byte <= 0x7A)) { // If upper case letter Byte -= 32; } SBUF0 = Byte; // Transmit to Hyperterminal UART_Output_First++; // Update counter UART_Buffer_Size--; // Decrease array size } else { UART_Buffer_Size = 0; // Set the array size to 0 TX_Ready = 1; // Indicate transmission complete } } } //----------------------------------------------------------------------------- // Timer2_Init //----------------------------------------------------------------------------- // // Configure Timer2 to 16-bit auto-reload and generate an interrupt at // interval specified by <counts> using SYSCLK/12 as its time base. // void Timer2_Init (int16_t counts) { TMR2CN = 0x00; // Stop Timer2; Clear TF2; // use SYSCLK/12 as timebase CKCON &= ~(CKCON_T2MH__BMASK | CKCON_T2ML__BMASK ); // Timer2 clocked based on TMR2CN_T2XCLK TMR2RL = -counts; // Init reload values TMR2 = 0xffff; // set to reload immediately IE_ET2 = 1; // enable Timer2 interrupts TMR2CN_TR2 = 1; // start Timer2 } //----------------------------------------------------------------------------- // Timer2_ISR //----------------------------------------------------------------------------- // This routine changes the state of the LED whenever Timer2 overflows. // SI_INTERRUPT(Timer2_ISR, TIMER2_IRQn) { TMR2CN_TF2H = 0; // clear Timer2 interrupt flag if(fSnap == KEY_DOWN) { SnapDown_TimeCnt++; // change state of LED if(SnapDown_TimeCnt==255) SnapDown_TimeCnt = 254; } else if(fRec == KEY_DOWN) { RecDown_TimeCnt++; // change state of LED if(RecDown_TimeCnt==255) RecDown_TimeCnt = 254; } } void MyDelay(uint16_t Value) { uint16_t i,j; for(i=0;i<Value;i++) { for(j=0;j<1000;j++) _nop_(); } } //----------------------------------------------------------------------------- // End Of File //-----------------------------------------------------------------------------
最新发布
07-04
### UART Communication and LED Control on C8051F300 Microcontroller The C8051F300 microcontroller is a popular choice for embedded systems due to its integrated peripherals, including UART communication capabilities. Understanding how to implement UART communication and control LEDs can be essential for various applications, such as data logging, sensor interfacing, and user feedback mechanisms. To establish UART communication, the microcontroller must be configured with appropriate settings for baud rate, data bits, parity, and stop bits. The following code snippet demonstrates how to initialize the UART module: ```c #include <C8051F300.h> void UART_Init(void) { SCON = 0x50; // Set UART mode to 8-bit, variable baud rate TMOD |= 0x20; // Timer 1 in mode 2 (8-bit auto-reload) TH1 = 0xFD; // Baud rate setting for 9600 bps TR1 = 1; // Start Timer 1 TI = 1; // Indicate that transmitter is ready } ``` In this initialization function, `SCON` is set to configure the UART for 8-bit data format with variable baud rate. The `TMOD` register is configured to operate Timer 1 in mode 2, which allows for an 8-bit auto-reload feature necessary for generating accurate baud rates. The value loaded into `TH1` determines the baud rate, where `0xFD` corresponds to a baud rate of 9600 bps[^1]. For LED control, the microcontroller's GPIO pins can be manipulated to turn LEDs on or off based on specific conditions within the program. Typically, an LED might be connected to a port pin through a current-limiting resistor to ground. Here's an example of how to toggle an LED connected to P1.0: ```c void Toggle_LED(void) { P1 ^= 0x01; // Toggle P1.0 } ``` This function uses bitwise XOR operation to invert the state of P1.0, effectively toggling the LED connected to it. Debugging issues related to UART communication often involves checking the configuration registers (`SCON`, `TMOD`, `TH1`) and ensuring that the correct baud rate is being used. Additionally, verifying the physical connections between devices and using oscilloscopes or logic analyzers can help identify timing issues or incorrect signal levels. When dealing with LED control, common problems include incorrect pin configurations, faulty wiring, or misinterpretation of active-high versus active-low signals. It's crucial to double-check the microcontroller's datasheet to ensure proper configuration of the I/O ports and any necessary pull-up or pull-down resistors.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值